home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / client.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  109KB  |  4,418 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB client
  5.    Copyright (C) Andrew Tridgell 1994-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include "includes.h"
  27.  
  28. #ifndef REGISTER
  29. #define REGISTER 0
  30. #endif
  31.  
  32. pstring cur_dir = "\\";
  33. pstring cd_path = "";
  34. pstring service="";
  35. pstring desthost="";
  36. pstring myname = "";
  37. pstring password = "";
  38. pstring username="";
  39. pstring workgroup=WORKGROUP;
  40. BOOL got_pass = False;
  41. BOOL connect_as_printer = False;
  42. BOOL connect_as_ipc = False;
  43.  
  44. char cryptkey[8];
  45. BOOL doencrypt=False;
  46.  
  47. extern pstring user_socket_options;
  48.  
  49. /* 30 second timeout on most commands */
  50. #define CLIENT_TIMEOUT (30*1000)
  51. #define SHORT_TIMEOUT (5*1000)
  52.  
  53. /* value for unused fid field in trans2 secondary request */
  54. #define FID_UNUSED (0xFFFF)
  55.  
  56. int name_type = 0x20;
  57.  
  58. int max_protocol = PROTOCOL_NT1;
  59.  
  60.  
  61. time_t newer_than = 0;
  62. int archive_level = 0;
  63.  
  64. extern struct in_addr myip;
  65.  
  66. extern pstring debugf;
  67. extern int DEBUGLEVEL;
  68.  
  69. BOOL translation = False;
  70.  
  71. /* clitar bits insert */
  72. extern void cmd_tar();
  73. extern void cmd_block();
  74. extern void cmd_tarmode();
  75. extern void cmd_setmode();
  76. extern int blocksize;
  77. extern BOOL tar_inc;
  78. extern BOOL tar_reset;
  79. /* clitar bits end */
  80.  
  81.  
  82. int cnum = 0;
  83. int pid = 0;
  84. int gid = 0;
  85. int uid = 0;
  86. int mid = 0;
  87. int myumask = 0755;
  88.  
  89. int max_xmit = BUFFER_SIZE;
  90.  
  91. extern pstring scope;
  92.  
  93. BOOL prompt = True;
  94.  
  95. int printmode = 1;
  96.  
  97. BOOL recurse = False;
  98. BOOL lowercase = False;
  99.  
  100. BOOL have_ip = False;
  101.  
  102. struct in_addr dest_ip;
  103.  
  104. #define SEPARATORS " \t\n\r"
  105.  
  106. BOOL abort_mget = True;
  107.  
  108. extern int Protocol;
  109.  
  110. BOOL readbraw_supported = False;
  111. BOOL writebraw_supported = False;
  112.  
  113. pstring fileselection = "";
  114.  
  115. extern file_info def_finfo;
  116.  
  117. /* timing globals */
  118. int get_total_size = 0;
  119. int get_total_time_ms = 0;
  120. int put_total_size = 0;
  121. int put_total_time_ms = 0;
  122.  
  123.  
  124. extern int Client;
  125.  
  126. #ifdef KANJI
  127. extern int coding_system;
  128. #define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
  129. #define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
  130. static BOOL
  131. setup_term_code (char *code)
  132. {
  133.     int new;
  134.     new = interpret_coding_system (code, UNKNOWN_CODE);
  135.     if (new != UNKNOWN_CODE) {
  136.     coding_system = new;
  137.     return True;
  138.     }
  139.     return False;
  140. }
  141. #else
  142. #define CNV_LANG(s) dos2unix_format(s,False)
  143. #define CNV_INPUT(s) unix2dos_format(s,True)
  144. #endif
  145.  
  146. static void send_logout(void );
  147. BOOL reopen_connection(char *inbuf,char *outbuf);
  148. static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir);
  149. static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir);
  150. static BOOL call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,
  151.              int *rprcnt,int *rdrcnt,char *param,char *data,
  152.              char **rparam,char **rdata);
  153. static BOOL send_trans_request(char *outbuf,int trans,
  154.                    char *name,int fid,int flags,
  155.                    char *data,char *param,uint16 *setup,
  156.                    int ldata,int lparam,int lsetup,
  157.                    int mdata,int mparam,int msetup);
  158.  
  159.  
  160. /****************************************************************************
  161. setup basics in a outgoing packet
  162. ****************************************************************************/
  163. void setup_pkt(char *outbuf)
  164. {
  165.   SSVAL(outbuf,smb_pid,pid);
  166.   SSVAL(outbuf,smb_uid,uid);
  167.   SSVAL(outbuf,smb_mid,mid);
  168.   if (Protocol > PROTOCOL_CORE)
  169.     {
  170.       SCVAL(outbuf,smb_flg,0x8);
  171.       SSVAL(outbuf,smb_flg2,0x1);
  172.     }
  173. }
  174.  
  175. /****************************************************************************
  176. write to a local file with CR/LF->LF translation if appropriate. return the 
  177. number taken from the buffer. This may not equal the number written.
  178. ****************************************************************************/
  179. static int writefile(int f, char *b, int n)
  180. {
  181.   int i;
  182.  
  183.   if (!translation)
  184.     return(write(f,b,n));
  185.   
  186.   i = 0;
  187.   while (i < n)
  188.     {
  189.       if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n')
  190.     {
  191.       b++;i++;
  192.     }
  193.       if (write(f, b, 1) != 1)
  194.     {
  195.       break;
  196.     }
  197.       b++;
  198.       i++;
  199.     }
  200.   
  201.   return(i);
  202. }
  203.  
  204. /****************************************************************************
  205.   read from a file with LF->CR/LF translation if appropriate. return the 
  206.   number read. read approx n bytes.
  207. ****************************************************************************/
  208. static int readfile(char *b, int size, int n, FILE *f)
  209. {
  210.   int i;
  211.   int c;
  212.  
  213.   if (!translation || (size != 1))
  214.     return(fread(b,size,n,f));
  215.   
  216.   i = 0;
  217.   while (i < n)
  218.     {
  219.       if ((c = getc(f)) == EOF)
  220.     {
  221.       break;
  222.     }
  223.       
  224.       if (c == '\n') /* change all LFs to CR/LF */
  225.     {
  226.       b[i++] = '\r';
  227.       n++;
  228.     }
  229.       
  230.       b[i++] = c;
  231.     }
  232.   
  233.   return(i);
  234. }
  235.  
  236.  
  237. /****************************************************************************
  238. read from a file with print translation. return the number read. read approx n
  239. bytes.
  240. ****************************************************************************/
  241. static int printread(FILE *f,char *b,int n)
  242. {
  243.   int i;
  244.  
  245.   i = readfile(b,1, n-1,f);
  246. #if FORMFEED
  247.   if (feof(f) && i>0)
  248.     b[i++] = '\014';
  249. #endif
  250.  
  251.   return(i);
  252. }
  253.  
  254. /****************************************************************************
  255. check for existance of a dir
  256. ****************************************************************************/
  257. static BOOL chkpath(char *path,BOOL report)
  258. {
  259.   fstring path2;
  260.   pstring inbuf,outbuf;
  261.   char *p;
  262.  
  263.   strcpy(path2,path);
  264.   trim_string(path2,NULL,"\\");
  265.   if (!*path2) *path2 = '\\';
  266.  
  267.   bzero(outbuf,smb_size);
  268.   set_message(outbuf,0,4 + strlen(path2),True);
  269.   SCVAL(outbuf,smb_com,SMBchkpth);
  270.   SSVAL(outbuf,smb_tid,cnum);
  271.   setup_pkt(outbuf);
  272.  
  273.   p = smb_buf(outbuf);
  274.   *p++ = 4;
  275.   strcpy(p,path2);
  276.  
  277.   send_smb(Client,outbuf);
  278.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  279.  
  280.   if (report && CVAL(inbuf,smb_rcls) != 0)
  281.     DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf)));
  282.  
  283.   return(CVAL(inbuf,smb_rcls) == 0);
  284. }
  285.  
  286.  
  287. /****************************************************************************
  288. send a message
  289. ****************************************************************************/
  290. static void send_message(char *inbuf,char *outbuf)
  291. {
  292.   int total_len = 0;
  293.  
  294.   char *p;
  295.   int grp_id;
  296.  
  297.   /* send a SMBsendstrt command */
  298.   bzero(outbuf,smb_size);
  299.   set_message(outbuf,0,0,True);
  300.   CVAL(outbuf,smb_com) = SMBsendstrt;
  301.   SSVAL(outbuf,smb_tid,cnum);
  302.  
  303.   p = smb_buf(outbuf);
  304.   *p++ = 4;
  305.   strcpy(p,username);
  306.   p = skip_string(p,1);
  307.   *p++ = 4;
  308.   strcpy(p,desthost);
  309.   p = skip_string(p,1);
  310.  
  311.   set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False);
  312.  
  313.   send_smb(Client,outbuf);
  314.   
  315.  
  316.   if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  317.     {
  318.       printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf));
  319.       return;
  320.     }
  321.  
  322.   grp_id = SVAL(inbuf,smb_vwv0);
  323.  
  324.   printf("Connected. Type your message, ending it with a Control-D\n");
  325.  
  326.   while (!feof(stdin) && total_len < 1600)
  327.     {
  328.       int maxlen = MIN(1600 - total_len,127);
  329.       pstring msg;
  330.       int l=0;
  331.       int c;
  332.  
  333.       bzero(msg,smb_size);
  334.  
  335.       for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++)
  336.     {
  337.       if (c == '\n')
  338.         msg[l++] = '\r';
  339.       msg[l] = c;   
  340.     }
  341.  
  342.       CVAL(outbuf,smb_com) = SMBsendtxt;
  343.  
  344.       set_message(outbuf,1,l+3,True);
  345.  
  346.       SSVAL(outbuf,smb_vwv0,grp_id);
  347.  
  348.       p = smb_buf(outbuf);
  349.       *p = 1;
  350.       SSVAL(p,1,l);
  351.       memcpy(p+3,msg,l);
  352.  
  353.       send_smb(Client,outbuf);
  354.       
  355.  
  356.       if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  357.     {
  358.       printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf));
  359.       return;
  360.     }      
  361.  
  362.       total_len += l;
  363.     }
  364.  
  365.   if (total_len >= 1600)
  366.     printf("the message was truncated to 1600 bytes ");
  367.   else
  368.     printf("sent %d bytes ",total_len);
  369.  
  370.   printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err));
  371.  
  372.   CVAL(outbuf,smb_com) = SMBsendend;
  373.   set_message(outbuf,1,0,False);
  374.   SSVAL(outbuf,smb_vwv0,grp_id);
  375.  
  376.   send_smb(Client,outbuf);
  377.   
  378.  
  379.   if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  380.     {
  381.       printf("SMBsendend failed (%s)\n",smb_errstr(inbuf));
  382.       return;
  383.     }      
  384. }
  385.  
  386.  
  387.  
  388. /****************************************************************************
  389. check the space on a device
  390. ****************************************************************************/
  391. static void do_dskattr(void)
  392. {
  393.   pstring inbuf,outbuf;
  394.  
  395.   bzero(outbuf,smb_size);
  396.   set_message(outbuf,0,0,True);
  397.   CVAL(outbuf,smb_com) = SMBdskattr;
  398.   SSVAL(outbuf,smb_tid,cnum);
  399.   setup_pkt(outbuf);
  400.  
  401.   send_smb(Client,outbuf);
  402.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  403.  
  404.   if (CVAL(inbuf,smb_rcls) != 0) 
  405.     DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf)));      
  406.  
  407.   DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n",
  408.     SVAL(inbuf,smb_vwv0),
  409.     SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2),
  410.     SVAL(inbuf,smb_vwv3)));
  411. }
  412.  
  413. /****************************************************************************
  414. show cd/pwd
  415. ****************************************************************************/
  416. static void cmd_pwd(void)
  417. {
  418.   DEBUG(0,("Current directory is %s",CNV_LANG(service)));
  419.   DEBUG(0,("%s\n",CNV_LANG(cur_dir)));
  420. }
  421.  
  422.  
  423. /****************************************************************************
  424. change directory
  425. ****************************************************************************/
  426. static void cmd_cd(char *inbuf,char *outbuf)
  427. {
  428.   fstring buf;
  429.   char *p = buf;
  430.   pstring saved_dir;
  431.  
  432.   if (next_token(NULL,buf,NULL))
  433.     {
  434.       pstring dname;
  435.       
  436.       /* Save the current directory in case the
  437.      new directory is invalid */
  438.       strcpy(saved_dir, cur_dir);
  439.       if (*p == '\\')
  440.     strcpy(cur_dir,p);
  441.       else
  442.     strcat(cur_dir,p);
  443.       if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
  444.     strcat(cur_dir, "\\");
  445.       }
  446.       dos_clean_name(cur_dir);
  447.       strcpy(dname,cur_dir);
  448.       strcat(cur_dir,"\\");
  449.       dos_clean_name(cur_dir);
  450.  
  451.       if (!strequal(cur_dir,"\\"))
  452.     if (!chkpath(dname,True))
  453.       strcpy(cur_dir,saved_dir);
  454.     }
  455.   else
  456.     DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir)));
  457.   strcpy(cd_path,cur_dir);
  458. }
  459.  
  460.  
  461. /****************************************************************************
  462.   display info about a file
  463.   ****************************************************************************/
  464. static void display_finfo(file_info *finfo)
  465. {
  466.   time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */
  467.   DEBUG(0,("  %-30s%7.7s%10d  %s",
  468.        CNV_LANG(finfo->name),
  469.        attrib_string(finfo->mode),
  470.        finfo->size,
  471.        asctime(LocalTime(&t,GMT_TO_LOCAL))));
  472. }
  473.  
  474. /****************************************************************************
  475.   do a directory listing, calling fn on each file found
  476.   ****************************************************************************/
  477. void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  478. {
  479.   if (Protocol >= PROTOCOL_LANMAN2)
  480.     {
  481.       if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0)
  482.     return;
  483.     }
  484.  
  485.   expand_mask(Mask,False);
  486.   do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir);
  487.   return;
  488. }
  489.  
  490. /*******************************************************************
  491.   decide if a file should be operated on
  492.   ********************************************************************/
  493. static BOOL do_this_one(file_info *finfo)
  494. {
  495.   if (finfo->mode & aDIR) return(True);
  496.  
  497.   if (newer_than && finfo->mtime < newer_than)
  498.     return(False);
  499.  
  500.   if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH))
  501.     return(False);
  502.  
  503.   return(True);
  504. }
  505.  
  506. /****************************************************************************
  507. interpret a short filename structure
  508. The length of the structure is returned
  509. ****************************************************************************/
  510. static int interpret_short_filename(char *p,file_info *finfo)
  511. {
  512.   finfo->mode = CVAL(p,21);
  513.  
  514.   /* this date is converted to GMT by make_unix_date */
  515.   finfo->ctime = make_unix_date(p+22);
  516.   finfo->mtime = finfo->atime = finfo->ctime;
  517.   finfo->size = IVAL(p,26);
  518.   strcpy(finfo->name,p+30);
  519.   
  520.   return(DIR_STRUCT_SIZE);
  521. }
  522.  
  523. /****************************************************************************
  524. interpret a long filename structure - this is mostly guesses at the moment
  525. The length of the structure is returned
  526. The structure of a long filename depends on the info level. 260 is used
  527. by NT and 2 is used by OS/2
  528. ****************************************************************************/
  529. static int interpret_long_filename(int level,char *p,file_info *finfo)
  530. {
  531.   if (finfo)
  532.     memcpy(finfo,&def_finfo,sizeof(*finfo));
  533.  
  534.   switch (level)
  535.     {
  536.     case 1: /* OS/2 understands this */
  537.       if (finfo)
  538.     {
  539.       /* these dates are converted to GMT by make_unix_date */
  540.       finfo->ctime = make_unix_date2(p+4);
  541.       finfo->atime = make_unix_date2(p+8);
  542.       finfo->mtime = make_unix_date2(p+12);
  543.       finfo->size = IVAL(p,16);
  544.       finfo->mode = CVAL(p,24);
  545.       strcpy(finfo->name,p+27);
  546.     }
  547.       return(28 + CVAL(p,26));
  548.  
  549.     case 2: /* this is what OS/2 uses mostly */
  550.       if (finfo)
  551.     {
  552.       /* these dates are converted to GMT by make_unix_date */
  553.       finfo->ctime = make_unix_date2(p+4);
  554.       finfo->atime = make_unix_date2(p+8);
  555.       finfo->mtime = make_unix_date2(p+12);
  556.       finfo->size = IVAL(p,16);
  557.       finfo->mode = CVAL(p,24);
  558.       strcpy(finfo->name,p+31);
  559.     }
  560.       return(32 + CVAL(p,30));
  561.  
  562.       /* levels 3 and 4 are untested */
  563.     case 3:
  564.       if (finfo)
  565.     {
  566.       /* these dates are probably like the other ones */
  567.       finfo->ctime = make_unix_date2(p+8);
  568.       finfo->atime = make_unix_date2(p+12);
  569.       finfo->mtime = make_unix_date2(p+16);
  570.       finfo->size = IVAL(p,20);
  571.       finfo->mode = CVAL(p,28);
  572.       strcpy(finfo->name,p+33);
  573.     }
  574.       return(SVAL(p,4)+4);
  575.  
  576.     case 4:
  577.       if (finfo)
  578.     {
  579.       /* these dates are probably like the other ones */
  580.       finfo->ctime = make_unix_date2(p+8);
  581.       finfo->atime = make_unix_date2(p+12);
  582.       finfo->mtime = make_unix_date2(p+16);
  583.       finfo->size = IVAL(p,20);
  584.       finfo->mode = CVAL(p,28);
  585.       strcpy(finfo->name,p+37);
  586.     }
  587.       return(SVAL(p,4)+4);
  588.  
  589.     case 260: /* NT uses this, but also accepts 2 */
  590.       if (finfo)
  591.     {
  592.       int ret = SVAL(p,0);
  593.       int namelen;
  594.       p += 4; /* next entry offset */
  595.       p += 4; /* fileindex */
  596.  
  597.       /* these dates appear to arrive in a weird way. It seems to
  598.          be localtime plus the serverzone given in the initial
  599.          connect. This is GMT when DST is not in effect and one
  600.          hour from GMT otherwise. Can this really be right??
  601.  
  602.          I suppose this could be called kludge-GMT. Is is the GMT
  603.          you get by using the current DST setting on a different
  604.          localtime. It will be cheap to calculate, I suppose, as
  605.          no DST tables will be needed */
  606.  
  607.       finfo->ctime = interpret_long_date(p); p += 8;
  608.       finfo->atime = interpret_long_date(p); p += 8;
  609.       finfo->mtime = interpret_long_date(p); p += 8; p += 8;
  610.       finfo->size = IVAL(p,0); p += 8;
  611.       p += 8; /* alloc size */
  612.       finfo->mode = CVAL(p,0); p += 4;
  613.       namelen = IVAL(p,0); p += 4;
  614.       p += 4; /* EA size */
  615.       p += 2; /* short name len? */
  616.       p += 24; /* short name? */      
  617.       StrnCpy(finfo->name,p,namelen);
  618.       return(ret);
  619.     }
  620.       return(SVAL(p,0));
  621.     }
  622.  
  623.   DEBUG(1,("Unknown long filename format %d\n",level));
  624.   return(SVAL(p,0));
  625. }
  626.  
  627.  
  628.  
  629.  
  630. /****************************************************************************
  631.   act on the files in a dir listing
  632.   ****************************************************************************/
  633. static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir)
  634. {
  635.  
  636.   if (!((finfo->mode & aDIR) == 0 && *fileselection && 
  637.     !mask_match(finfo->name,fileselection,False,False)) &&
  638.       !(recurse_dir && (strequal(finfo->name,".") || 
  639.             strequal(finfo->name,".."))))
  640.     {
  641.       if (recurse_dir && (finfo->mode & aDIR))
  642.     {
  643.       pstring mask2;
  644.       pstring sav_dir;
  645.       strcpy(sav_dir,cur_dir);
  646.       strcat(cur_dir,finfo->name);
  647.       strcat(cur_dir,"\\");
  648.       strcpy(mask2,cur_dir);
  649.  
  650.       if (!fn)
  651.         DEBUG(0,("\n%s\n",CNV_LANG(cur_dir)));
  652.  
  653.       if (longdir)
  654.         {
  655.           strcat(mask2,"*");
  656.           do_long_dir(inbuf,outbuf,mask2,attribute,fn,True);      
  657.         }
  658.       else
  659.         {
  660.           strcat(mask2,"*.*");
  661.           do_dir(inbuf,outbuf,mask2,attribute,fn,True);
  662.         }
  663.       strcpy(cur_dir,sav_dir);
  664.     }
  665.       else
  666.     {
  667.       if (fn && do_this_one(finfo))
  668.         fn(finfo);
  669.     }
  670.     }
  671. }
  672.  
  673.  
  674. /****************************************************************************
  675.   do a directory listing, calling fn on each file found
  676.   ****************************************************************************/
  677. static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  678. {
  679.   char *p;
  680.   int received = 0;
  681.   BOOL first = True;
  682.   char status[21];
  683.   int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE;
  684.   int num_received = 0;
  685.   int i;
  686.   char *dirlist = NULL;
  687.   pstring mask;
  688.   file_info finfo;
  689.  
  690.   finfo = def_finfo;
  691.  
  692.   bzero(status,21);
  693.  
  694.   strcpy(mask,Mask);
  695.   
  696.   while (1)
  697.     {
  698.       bzero(outbuf,smb_size);
  699.       if (first)    
  700.     set_message(outbuf,2,5 + strlen(mask),True);
  701.       else
  702.     set_message(outbuf,2,5 + 21,True);
  703.  
  704. #if FFIRST
  705.       if (Protocol >= PROTOCOL_LANMAN1)
  706.     CVAL(outbuf,smb_com) = SMBffirst;
  707.       else
  708. #endif
  709.     CVAL(outbuf,smb_com) = SMBsearch;
  710.  
  711.       SSVAL(outbuf,smb_tid,cnum);
  712.       setup_pkt(outbuf);
  713.  
  714.       SSVAL(outbuf,smb_vwv0,num_asked);
  715.       SSVAL(outbuf,smb_vwv1,attribute);
  716.   
  717.       p = smb_buf(outbuf);
  718.       *p++ = 4;
  719.       
  720.       if (first)
  721.     strcpy(p,mask);
  722.       else
  723.     strcpy(p,"");
  724.       p += strlen(p) + 1;
  725.       
  726.       *p++ = 5;
  727.       if (first)
  728.     SSVAL(p,0,0);
  729.       else
  730.     {
  731.       SSVAL(p,0,21);
  732.       p += 2;
  733.       memcpy(p,status,21);
  734.     }
  735.  
  736.       send_smb(Client,outbuf);
  737.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  738.  
  739.       received = SVAL(inbuf,smb_vwv0);
  740.  
  741.       DEBUG(5,("dir received %d\n",received));
  742.  
  743.       DEBUG(6,("errstr=%s\n",smb_errstr(inbuf)));
  744.  
  745.       if (received <= 0) break;
  746.  
  747.       first = False;
  748.  
  749.       dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
  750.  
  751.       if (!dirlist) 
  752.     return 0;
  753.  
  754.       p = smb_buf(inbuf) + 3;
  755.  
  756.       memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
  757.          p,received*DIR_STRUCT_SIZE);
  758.  
  759.       memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
  760.  
  761.       num_received += received;
  762.  
  763.       if (CVAL(inbuf,smb_rcls) != 0) break;
  764.     }
  765.  
  766. #if FFIRST
  767.   if (!first && Protocol >= PROTOCOL_LANMAN1)
  768.     {
  769.       bzero(outbuf,smb_size);
  770.       CVAL(outbuf,smb_com) = SMBfclose;
  771.  
  772.       SSVAL(outbuf,smb_tid,cnum);
  773.       setup_pkt(outbuf);
  774.  
  775.       p = smb_buf(outbuf);
  776.       *p++ = 4;
  777.       
  778.       strcpy(p,"");
  779.       p += strlen(p) + 1;
  780.       
  781.       *p++ = 5;
  782.       SSVAL(p,0,21);
  783.       p += 2;
  784.       memcpy(p,status,21);
  785.  
  786.       send_smb(Client,outbuf);
  787.       receive_smb(Client,inbuf,CLIENT_TIMEOUT,False);
  788.  
  789.       if (CVAL(inbuf,smb_rcls) != 0) 
  790.     DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));      
  791.     }
  792. #endif
  793.  
  794.   if (!fn)
  795.     for (p=dirlist,i=0;i<num_received;i++)
  796.       {
  797.     p += interpret_short_filename(p,&finfo);
  798.     display_finfo(&finfo);
  799.       }
  800.  
  801.   for (p=dirlist,i=0;i<num_received;i++)
  802.     {
  803.       p += interpret_short_filename(p,&finfo);
  804.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False);
  805.     }
  806.  
  807.   if (dirlist) free(dirlist);
  808.   return(num_received);
  809. }
  810.  
  811. /****************************************************************************
  812.   receive a SMB trans or trans2 response allocating the necessary memory
  813.   ****************************************************************************/
  814. static BOOL receive_trans_response(char *inbuf,int trans,
  815.                                    int *data_len,int *param_len,
  816.                       char **data,char **param)
  817. {
  818.   int total_data=0;
  819.   int total_param=0;
  820.   int this_data,this_param;
  821.  
  822.   *data_len = *param_len = 0;
  823.  
  824.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  825.   show_msg(inbuf);
  826.  
  827.   /* sanity check */
  828.   if (CVAL(inbuf,smb_com) != trans)
  829.     {
  830.       DEBUG(0,("Expected %s response, got command 0x%02x\n",
  831.            trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
  832.       return(False);
  833.     }
  834.   if (CVAL(inbuf,smb_rcls) != 0)
  835.     return(False);
  836.  
  837.   /* parse out the lengths */
  838.   total_data = SVAL(inbuf,smb_tdrcnt);
  839.   total_param = SVAL(inbuf,smb_tprcnt);
  840.  
  841.   /* allocate it */
  842.   *data = Realloc(*data,total_data);
  843.   *param = Realloc(*param,total_param);
  844.  
  845.   while (1)
  846.     {
  847.       this_data = SVAL(inbuf,smb_drcnt);
  848.       this_param = SVAL(inbuf,smb_prcnt);
  849.       if (this_data)
  850.     memcpy(*data + SVAL(inbuf,smb_drdisp),
  851.            smb_base(inbuf) + SVAL(inbuf,smb_droff),
  852.            this_data);
  853.       if (this_param)
  854.     memcpy(*param + SVAL(inbuf,smb_prdisp),
  855.            smb_base(inbuf) + SVAL(inbuf,smb_proff),
  856.            this_param);
  857.       *data_len += this_data;
  858.       *param_len += this_param;
  859.  
  860.       /* parse out the total lengths again - they can shrink! */
  861.       total_data = SVAL(inbuf,smb_tdrcnt);
  862.       total_param = SVAL(inbuf,smb_tprcnt);
  863.  
  864.       if (total_data <= *data_len && total_param <= *param_len)
  865.     break;
  866.  
  867.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  868.       show_msg(inbuf);
  869.  
  870.       /* sanity check */
  871.       if (CVAL(inbuf,smb_com) != trans)
  872.     {
  873.       DEBUG(0,("Expected %s response, got command 0x%02x\n",
  874.            trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
  875.       return(False);
  876.     }
  877.       if (CVAL(inbuf,smb_rcls) != 0)
  878.       return(False);
  879.     }
  880.   
  881.   return(True);
  882. }
  883.  
  884. /****************************************************************************
  885.   do a directory listing, calling fn on each file found. Use the TRANSACT2
  886.   call for long filenames
  887.   ****************************************************************************/
  888. static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir)
  889. {
  890.   int max_matches = 512;
  891.   int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */
  892.   char *p;
  893.   pstring mask;
  894.   file_info finfo;
  895.   int i;
  896.   char *dirlist = NULL;
  897.   int dirlist_len = 0;
  898.   int total_received = 0;
  899.   BOOL First = True;
  900.   char *resp_data=NULL;
  901.   char *resp_param=NULL;
  902.   int resp_data_len = 0;
  903.   int resp_param_len=0;
  904.  
  905.   int ff_resume_key = 0;
  906.   int ff_searchcount=0;
  907.   int ff_eos=0;
  908.   int ff_lastname=0;
  909.   int ff_dir_handle=0;
  910.   int loop_count = 0;
  911.  
  912.   uint16 setup;
  913.   pstring param;
  914.  
  915.   strcpy(mask,Mask);
  916.  
  917.   while (ff_eos == 0)
  918.     {
  919.       loop_count++;
  920.       if (loop_count > 200)
  921.     {
  922.       DEBUG(0,("ERROR: Looping in FIND_NEXT??\n"));
  923.       break;
  924.     }
  925.  
  926.       if (First)
  927.     {
  928.       setup = TRANSACT2_FINDFIRST;
  929.       SSVAL(param,0,attribute); /* attribute */
  930.       SSVAL(param,2,max_matches); /* max count */
  931.       SSVAL(param,4,8+4+2);    /* resume required + close on end + continue */
  932.       SSVAL(param,6,info_level); 
  933.       SIVAL(param,8,0);
  934.       strcpy(param+12,mask);
  935.     }
  936.       else
  937.     {
  938.       setup = TRANSACT2_FINDNEXT;
  939.       SSVAL(param,0,ff_dir_handle);
  940.       SSVAL(param,2,max_matches); /* max count */
  941.       SSVAL(param,4,info_level); 
  942.       SIVAL(param,6,ff_resume_key); /* ff_resume_key */
  943.       SSVAL(param,10,8+4+2);    /* resume required + close on end + continue */
  944.       strcpy(param+12,mask);
  945.  
  946.       DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
  947.            ff_dir_handle,ff_resume_key,ff_lastname,mask));
  948.     }
  949.       /* ??? original code added 1 pad byte after param */
  950.  
  951.       send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
  952.              NULL,param,&setup,
  953.              0,12+strlen(mask)+1,1,
  954.              BUFFER_SIZE,10,0);
  955.  
  956.       if (!receive_trans_response(inbuf,SMBtrans2,
  957.                   &resp_data_len,&resp_param_len,
  958.                       &resp_data,&resp_param))
  959.     {
  960.       DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf)));
  961.       break;
  962.     }
  963.  
  964.       /* parse out some important return info */
  965.       p = resp_param;
  966.       if (First)
  967.     {
  968.       ff_dir_handle = SVAL(p,0);
  969.       ff_searchcount = SVAL(p,2);
  970.       ff_eos = SVAL(p,4);
  971.       ff_lastname = SVAL(p,8);
  972.     }
  973.       else
  974.     {
  975.       ff_searchcount = SVAL(p,0);
  976.       ff_eos = SVAL(p,2);
  977.       ff_lastname = SVAL(p,6);
  978.     }
  979.  
  980.       if (ff_searchcount == 0) 
  981.     break;
  982.  
  983.       /* point to the data bytes */
  984.       p = resp_data;
  985.  
  986.       /* we might need the lastname for continuations */
  987.       if (ff_lastname > 0)
  988.     {
  989.       switch(info_level)
  990.         {
  991.         case 260:
  992.           ff_resume_key =0;
  993.           StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname);
  994.           /* strcpy(mask,p+ff_lastname+94); */
  995.           break;
  996.         case 1:
  997.           strcpy(mask,p + ff_lastname + 1);
  998.           ff_resume_key = 0;
  999.           break;
  1000.         }
  1001.     }
  1002.       else
  1003.     strcpy(mask,"");
  1004.   
  1005.       /* and add them to the dirlist pool */
  1006.       dirlist = Realloc(dirlist,dirlist_len + resp_data_len);
  1007.  
  1008.       if (!dirlist)
  1009.     {
  1010.       DEBUG(0,("Failed to expand dirlist\n"));
  1011.       break;
  1012.     }
  1013.  
  1014.       /* put in a length for the last entry, to ensure we can chain entries 
  1015.      into the next packet */
  1016.       {
  1017.     char *p2;
  1018.     for (p2=p,i=0;i<(ff_searchcount-1);i++)
  1019.       p2 += interpret_long_filename(info_level,p2,NULL);
  1020.     SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p));
  1021.       }
  1022.  
  1023.       /* grab the data for later use */
  1024.       memcpy(dirlist+dirlist_len,p,resp_data_len);
  1025.       dirlist_len += resp_data_len;
  1026.  
  1027.       total_received += ff_searchcount;
  1028.  
  1029.       if (resp_data) free(resp_data); resp_data = NULL;
  1030.       if (resp_param) free(resp_param); resp_param = NULL;
  1031.  
  1032.       DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
  1033.            ff_searchcount,ff_eos,ff_resume_key));
  1034.  
  1035.       First = False;
  1036.     }
  1037.  
  1038.   if (!fn)
  1039.     for (p=dirlist,i=0;i<total_received;i++)
  1040.       {
  1041.     p += interpret_long_filename(info_level,p,&finfo);
  1042.     display_finfo(&finfo);
  1043.       }
  1044.  
  1045.   for (p=dirlist,i=0;i<total_received;i++)
  1046.     {
  1047.       p += interpret_long_filename(info_level,p,&finfo);
  1048.       dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True);
  1049.     }
  1050.  
  1051.   /* free up the dirlist buffer */
  1052.   if (dirlist) free(dirlist);
  1053.   return(total_received);
  1054. }
  1055.  
  1056.  
  1057. /****************************************************************************
  1058.   get a directory listing
  1059.   ****************************************************************************/
  1060. static void cmd_dir(char *inbuf,char *outbuf)
  1061. {
  1062.   int attribute = aDIR | aSYSTEM | aHIDDEN;
  1063.   pstring mask;
  1064.   fstring buf;
  1065.   char *p=buf;
  1066.  
  1067.   strcpy(mask,cur_dir);
  1068.   if(mask[strlen(mask)-1]!='\\')
  1069.     strcat(mask,"\\");
  1070.  
  1071.   if (next_token(NULL,buf,NULL))
  1072.     {
  1073.       if (*p == '\\')
  1074.     strcpy(mask,p);
  1075.       else
  1076.     strcat(mask,p);
  1077.     }
  1078.   else {
  1079.     if (Protocol < PROTOCOL_NT1)
  1080.       strcat(mask,"*.*");
  1081.     else
  1082.       strcat(mask,"*");
  1083.   }
  1084.  
  1085.   do_dir(inbuf,outbuf,mask,attribute,NULL,recurse);
  1086.  
  1087.   do_dskattr();
  1088. }
  1089.  
  1090.  
  1091.  
  1092. /****************************************************************************
  1093.   get a file from rname to lname
  1094.   ****************************************************************************/
  1095. static void do_get(char *rname,char *lname,file_info *finfo1)
  1096. {  
  1097.   int handle=0,fnum;
  1098.   uint32 nread=0;
  1099.   char *p;
  1100.   BOOL newhandle = False;
  1101.   char *inbuf,*outbuf;
  1102.   file_info finfo;
  1103.   BOOL close_done = False;
  1104.   BOOL ignore_close_error = False;
  1105.   char *dataptr=NULL;
  1106.   int datalen=0;
  1107.  
  1108.   struct timeval tp_start;
  1109.   GetTimeOfDay(&tp_start);
  1110.  
  1111.   if (finfo1) 
  1112.     finfo = *finfo1;
  1113.   else
  1114.     finfo = def_finfo;
  1115.  
  1116.   if (lowercase)
  1117.     strlower(lname);
  1118.  
  1119.  
  1120.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1121.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1122.  
  1123.   if (!inbuf || !outbuf)
  1124.     {
  1125.       DEBUG(0,("out of memory\n"));
  1126.       return;
  1127.     }
  1128.  
  1129.   bzero(outbuf,smb_size);
  1130.   set_message(outbuf,15,1 + strlen(rname),True);
  1131.  
  1132.   CVAL(outbuf,smb_com) = SMBopenX;
  1133.   SSVAL(outbuf,smb_tid,cnum);
  1134.   setup_pkt(outbuf);
  1135.  
  1136.   SSVAL(outbuf,smb_vwv0,0xFF);
  1137.   SSVAL(outbuf,smb_vwv2,1);
  1138.   SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
  1139.   SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
  1140.   SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
  1141.   SSVAL(outbuf,smb_vwv8,1);
  1142.   
  1143.   p = smb_buf(outbuf);
  1144.   strcpy(p,rname);
  1145.   p = skip_string(p,1);
  1146.  
  1147.   /* do a chained openX with a readX? */
  1148. #if 1
  1149.   if (finfo.size > 0)
  1150.     {
  1151.       DEBUG(3,("Chaining readX wth openX\n"));
  1152.       SSVAL(outbuf,smb_vwv0,SMBreadX);
  1153.       SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf));
  1154.       bzero(p,200);
  1155.       p -= smb_wct;
  1156.       SSVAL(p,smb_wct,10);
  1157.       SSVAL(p,smb_vwv0,0xFF);
  1158.       SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
  1159.       SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size));
  1160.       smb_setlen(outbuf,smb_len(outbuf)+11*2+1);  
  1161.     }
  1162. #endif
  1163.  
  1164.   if(!strcmp(lname,"-"))
  1165.     handle = fileno(stdout);
  1166.   else 
  1167.     {
  1168.       handle = creat(lname,0644);
  1169.       newhandle = True;
  1170.     }
  1171.   if (handle < 0)
  1172.     {
  1173.       DEBUG(0,("Error opening local file %s\n",lname));
  1174.       free(inbuf);free(outbuf);
  1175.       return;
  1176.     }
  1177.  
  1178.   send_smb(Client,outbuf);
  1179.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1180.  
  1181.   if (CVAL(inbuf,smb_rcls) != 0)
  1182.     {
  1183.       if (CVAL(inbuf,smb_rcls) == ERRSRV &&
  1184.       SVAL(inbuf,smb_err) == ERRnoresource &&
  1185.       reopen_connection(inbuf,outbuf))
  1186.     {
  1187.       do_get(rname,lname,finfo1);
  1188.       return;
  1189.     }
  1190.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1191.       if(newhandle)
  1192.     close(handle);
  1193.       free(inbuf);free(outbuf);
  1194.       return;
  1195.     }
  1196.  
  1197.   strcpy(finfo.name,rname);
  1198.  
  1199.   if (!finfo1)
  1200.     {
  1201.       finfo.mode = SVAL(inbuf,smb_vwv3);
  1202.       /* these times arrive as LOCAL time, using the DST offset 
  1203.      corresponding to that time, we convert them to GMT */
  1204.       finfo.mtime = make_unix_date3(inbuf+smb_vwv4);
  1205.       finfo.atime = finfo.ctime = finfo.mtime;
  1206.       finfo.size = IVAL(inbuf,smb_vwv6);
  1207.     }
  1208.  
  1209.   DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode));
  1210.  
  1211.   fnum = SVAL(inbuf,smb_vwv2);
  1212.  
  1213.   /* we might have got some data from a chained readX */
  1214.   if (SVAL(inbuf,smb_vwv0) == SMBreadX)
  1215.     {
  1216.       p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct;
  1217.       datalen = SVAL(p,smb_vwv5);
  1218.       dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6);
  1219.     }
  1220.   else
  1221.     {
  1222.       dataptr = NULL;
  1223.       datalen = 0;
  1224.     }
  1225.  
  1226.  
  1227.   DEBUG(2,("getting file %s of size %d bytes as %s ",
  1228.        CNV_LANG(finfo.name),
  1229.        finfo.size,
  1230.        lname));
  1231.  
  1232.   while (nread < finfo.size && !close_done)
  1233.     {
  1234.       int method = -1;
  1235.       static BOOL can_chain_close = True;
  1236.  
  1237.       p=NULL;
  1238.       
  1239.       DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size));
  1240.  
  1241.       /* 3 possible read types. readbraw if a large block is required.
  1242.      readX + close if not much left and read if neither is supported */
  1243.  
  1244.       /* we might have already read some data from a chained readX */
  1245.       if (dataptr && datalen>0)
  1246.     method=3;
  1247.  
  1248.       /* if we can finish now then readX+close */
  1249.       if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && 
  1250.       ((finfo.size - nread) < 
  1251.        (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300))))
  1252.     method = 0;
  1253.  
  1254.       /* if we support readraw then use that */
  1255.       if (method<0 && readbraw_supported)
  1256.     method = 1;
  1257.  
  1258.       /* if we can then use readX */
  1259.       if (method<0 && (Protocol >= PROTOCOL_LANMAN1))
  1260.     method = 2;
  1261.  
  1262.       switch (method)
  1263.     {
  1264.       /* use readX */
  1265.     case 0:
  1266.     case 2:
  1267.       if (method == 0)
  1268.         close_done = True;
  1269.         
  1270.       /* use readX + close */
  1271.       bzero(outbuf,smb_size);
  1272.       set_message(outbuf,10,0,True);
  1273.       CVAL(outbuf,smb_com) = SMBreadX;
  1274.       SSVAL(outbuf,smb_tid,cnum);
  1275.       setup_pkt(outbuf);
  1276.       
  1277.       if (close_done)
  1278.         {
  1279.           CVAL(outbuf,smb_vwv0) = SMBclose;
  1280.           SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf));
  1281.         }
  1282.       else
  1283.         CVAL(outbuf,smb_vwv0) = 0xFF;          
  1284.       
  1285.       SSVAL(outbuf,smb_vwv2,fnum);
  1286.       SIVAL(outbuf,smb_vwv3,nread);
  1287.       SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread));
  1288.       SSVAL(outbuf,smb_vwv6,0);
  1289.       SIVAL(outbuf,smb_vwv7,0);
  1290.       SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread));
  1291.       
  1292.       if (close_done)
  1293.         {
  1294.           p = smb_buf(outbuf);
  1295.           bzero(p,9);
  1296.           
  1297.           CVAL(p,0) = 3;
  1298.           SSVAL(p,1,fnum);
  1299.           SIVALS(p,3,-1);
  1300.           
  1301.           /* now set the total packet length */
  1302.           smb_setlen(outbuf,smb_len(outbuf)+9);
  1303.         }
  1304.       
  1305.       send_smb(Client,outbuf);
  1306.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1307.       
  1308.       if (CVAL(inbuf,smb_rcls) != 0)
  1309.         {
  1310.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1311.           break;
  1312.         }
  1313.       
  1314.       if (close_done &&
  1315.           SVAL(inbuf,smb_vwv0) != SMBclose)
  1316.         {
  1317.           /* NOTE: WfWg sometimes just ignores the chained
  1318.          command! This seems to break the spec? */
  1319.           DEBUG(3,("Rejected chained close?\n"));
  1320.           close_done = False;
  1321.           can_chain_close = False;
  1322.           ignore_close_error = True;
  1323.         }
  1324.       
  1325.       datalen = SVAL(inbuf,smb_vwv5);
  1326.       dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6);
  1327.       break;
  1328.  
  1329.       /* use readbraw */
  1330.     case 1:
  1331.       {
  1332.         static int readbraw_size = BUFFER_SIZE;
  1333.       
  1334.         extern int Client;
  1335.         bzero(outbuf,smb_size);
  1336.         set_message(outbuf,8,0,True);
  1337.         CVAL(outbuf,smb_com) = SMBreadbraw;
  1338.         SSVAL(outbuf,smb_tid,cnum);
  1339.         setup_pkt(outbuf);
  1340.         SSVAL(outbuf,smb_vwv0,fnum);
  1341.         SIVAL(outbuf,smb_vwv1,nread);
  1342.         SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
  1343.         SSVAL(outbuf,smb_vwv4,0);
  1344.         SIVALS(outbuf,smb_vwv5,-1);
  1345.         send_smb(Client,outbuf);
  1346.  
  1347.         /* Now read the raw data into the buffer and write it */      
  1348.         if(read_smb_length(Client,inbuf,0) == -1) {
  1349.           DEBUG(0,("Failed to read length in readbraw\n"));        
  1350.           exit(1);
  1351.         }
  1352.         
  1353.         /* Even though this is not an smb message, smb_len
  1354.            returns the generic length of an smb message */
  1355.         datalen = smb_len(inbuf);
  1356.  
  1357.         if (datalen == 0)
  1358.           {
  1359.         /* we got a readbraw error */
  1360.         DEBUG(4,("readbraw error - reducing size\n"));
  1361.         readbraw_size = (readbraw_size * 9) / 10;
  1362.         
  1363.         if (readbraw_size < max_xmit)
  1364.           {
  1365.             DEBUG(0,("disabling readbraw\n"));
  1366.             readbraw_supported = False;
  1367.           }
  1368.         
  1369.         dataptr=NULL;
  1370.         continue;
  1371.           }
  1372.  
  1373.         if(read_data(Client,inbuf,datalen) != datalen) {
  1374.           DEBUG(0,("Failed to read data in readbraw\n"));
  1375.           exit(1);
  1376.         }
  1377.         dataptr = inbuf;
  1378.       }
  1379.       break;
  1380.  
  1381.     case 3:
  1382.       /* we've already read some data with a chained readX */
  1383.       break;
  1384.  
  1385.     default:
  1386.       /* use plain read */
  1387.       bzero(outbuf,smb_size);
  1388.       set_message(outbuf,5,0,True);
  1389.       CVAL(outbuf,smb_com) = SMBread;
  1390.       SSVAL(outbuf,smb_tid,cnum);
  1391.       setup_pkt(outbuf);
  1392.  
  1393.       SSVAL(outbuf,smb_vwv0,fnum);
  1394.       SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
  1395.       SIVAL(outbuf,smb_vwv2,nread);
  1396.       SSVAL(outbuf,smb_vwv4,finfo.size - nread);
  1397.  
  1398.       send_smb(Client,outbuf);
  1399.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1400.  
  1401.       if (CVAL(inbuf,smb_rcls) != 0)
  1402.         {
  1403.           DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf)));
  1404.           break;
  1405.         }
  1406.  
  1407.       datalen = SVAL(inbuf,smb_vwv0);
  1408.       dataptr = smb_buf(inbuf) + 3;
  1409.       break;
  1410.     }
  1411.  
  1412.       if (writefile(handle,dataptr,datalen) != datalen)
  1413.     {
  1414.       DEBUG(0,("Error writing local file\n"));
  1415.       break;
  1416.     }
  1417.       
  1418.       nread += datalen;
  1419.       if (datalen == 0) 
  1420.     {
  1421.       DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread));
  1422.       break;
  1423.     }
  1424.  
  1425.       dataptr=NULL;
  1426.       datalen=0;
  1427.     }
  1428.  
  1429.  
  1430.  
  1431.   if (!close_done)
  1432.     {
  1433.       bzero(outbuf,smb_size);
  1434.       set_message(outbuf,3,0,True);
  1435.       CVAL(outbuf,smb_com) = SMBclose;
  1436.       SSVAL(outbuf,smb_tid,cnum);
  1437.       setup_pkt(outbuf);
  1438.       
  1439.       SSVAL(outbuf,smb_vwv0,fnum);
  1440.       SIVALS(outbuf,smb_vwv1,-1);
  1441.       
  1442.       send_smb(Client,outbuf);
  1443.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1444.       
  1445.       if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
  1446.     {
  1447.       DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf)));
  1448.       if(newhandle)
  1449.         close(handle);
  1450.       free(inbuf);free(outbuf);
  1451.       return;
  1452.     }
  1453.     }
  1454.  
  1455.   if(newhandle)
  1456.     close(handle);
  1457.  
  1458.   if (archive_level >= 2 && (finfo.mode & aARCH)) {
  1459.     bzero(outbuf,smb_size);
  1460.     set_message(outbuf,8,strlen(rname)+4,True);
  1461.     CVAL(outbuf,smb_com) = SMBsetatr;
  1462.     SSVAL(outbuf,smb_tid,cnum);
  1463.     setup_pkt(outbuf);
  1464.     SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
  1465.     SIVALS(outbuf,smb_vwv1,0);
  1466.     p = smb_buf(outbuf);
  1467.     *p++ = 4;
  1468.     strcpy(p,rname);
  1469.     p += strlen(p)+1;
  1470.     *p++ = 4;
  1471.     *p = 0;
  1472.     send_smb(Client,outbuf);
  1473.     receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1474.   }
  1475.  
  1476.   {
  1477.     struct timeval tp_end;
  1478.     int this_time;
  1479.  
  1480.     GetTimeOfDay(&tp_end);
  1481.     this_time = 
  1482.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1483.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1484.     get_total_time_ms += this_time;
  1485.     get_total_size += finfo.size;
  1486.  
  1487.     DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
  1488.          finfo.size / (1.024*this_time + 1.0e-4),
  1489.          get_total_size / (1.024*get_total_time_ms)));
  1490.   }
  1491.  
  1492.   free(inbuf);free(outbuf);
  1493. }
  1494.  
  1495.  
  1496. /****************************************************************************
  1497.   get a file
  1498.   ****************************************************************************/
  1499. static void cmd_get(void)
  1500. {
  1501.   pstring lname;
  1502.   pstring rname;
  1503.   char *p;
  1504.  
  1505.   strcpy(rname,cur_dir);
  1506.   strcat(rname,"\\");
  1507.  
  1508.   p = rname + strlen(rname);
  1509.  
  1510.   if (!next_token(NULL,p,NULL)) {
  1511.     DEBUG(0,("get <filename>\n"));
  1512.     return;
  1513.   }
  1514.   strcpy(lname,p);
  1515.   dos_clean_name(rname);
  1516.     
  1517.   next_token(NULL,lname,NULL);
  1518.  
  1519.   do_get(rname,lname,NULL);
  1520. }
  1521.  
  1522.  
  1523. /****************************************************************************
  1524.   do a mget operation on one file
  1525.   ****************************************************************************/
  1526. static void do_mget(file_info *finfo)
  1527. {
  1528.   pstring rname;
  1529.   pstring quest;
  1530.  
  1531.   if (strequal(finfo->name,".") || strequal(finfo->name,".."))
  1532.     return;
  1533.  
  1534.   if (abort_mget)
  1535.     {
  1536.       DEBUG(0,("mget aborted\n"));
  1537.       return;
  1538.     }
  1539.  
  1540.   if (finfo->mode & aDIR)
  1541.     sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name));
  1542.   else
  1543.     sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name));
  1544.  
  1545.   if (prompt && !yesno(quest)) return;
  1546.  
  1547.   if (finfo->mode & aDIR)
  1548.     {
  1549.       pstring saved_curdir;
  1550.       pstring mget_mask;
  1551.       char *inbuf,*outbuf;
  1552.  
  1553.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1554.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1555.  
  1556.       if (!inbuf || !outbuf)
  1557.     {
  1558.       DEBUG(0,("out of memory\n"));
  1559.       return;
  1560.     }
  1561.  
  1562.       strcpy(saved_curdir,cur_dir);
  1563.  
  1564.       strcat(cur_dir,finfo->name);
  1565.       strcat(cur_dir,"\\");
  1566.  
  1567.       unix_format(finfo->name);
  1568.       {
  1569.     if (lowercase)
  1570.       strlower(finfo->name);
  1571.  
  1572.     if (!directory_exist(finfo->name,NULL) && 
  1573.         sys_mkdir(finfo->name,0777) != 0) 
  1574.       {
  1575.         DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name)));
  1576.         strcpy(cur_dir,saved_curdir);
  1577.         free(inbuf);free(outbuf);
  1578.         return;
  1579.       }
  1580.  
  1581.     if (sys_chdir(finfo->name) != 0)
  1582.       {
  1583.         DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name)));
  1584.         strcpy(cur_dir,saved_curdir);
  1585.         free(inbuf);free(outbuf);
  1586.         return;
  1587.       }
  1588.       }       
  1589.  
  1590.       strcpy(mget_mask,cur_dir);
  1591.       strcat(mget_mask,"*.*");
  1592.       
  1593.       do_dir((char *)inbuf,(char *)outbuf,
  1594.          mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False);
  1595.       chdir("..");
  1596.       strcpy(cur_dir,saved_curdir);
  1597.       free(inbuf);free(outbuf);
  1598.     }
  1599.   else
  1600.     {
  1601.       strcpy(rname,cur_dir);
  1602.       strcat(rname,finfo->name);
  1603.       do_get(rname,finfo->name,finfo);
  1604.     }
  1605. }
  1606.  
  1607. /****************************************************************************
  1608. view the file using the pager
  1609. ****************************************************************************/
  1610. static void cmd_more(void)
  1611. {
  1612.   fstring rname,lname,tmpname,pager_cmd;
  1613.   char *pager;
  1614.  
  1615.   strcpy(rname,cur_dir);
  1616.   strcat(rname,"\\");
  1617.   sprintf(tmpname,"/tmp/smbmore.%d",getpid());
  1618.   strcpy(lname,tmpname);
  1619.  
  1620.   if (!next_token(NULL,rname+strlen(rname),NULL)) {
  1621.     DEBUG(0,("more <filename>\n"));
  1622.     return;
  1623.   }
  1624.   dos_clean_name(rname);
  1625.  
  1626.   do_get(rname,lname,NULL);
  1627.  
  1628.   pager=getenv("PAGER");
  1629.   sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname);
  1630.   system(pager_cmd);
  1631.   unlink(tmpname);
  1632. }
  1633.  
  1634.  
  1635.  
  1636. /****************************************************************************
  1637. do a mget command
  1638. ****************************************************************************/
  1639. static void cmd_mget(char *inbuf,char *outbuf)
  1640. {
  1641.   int attribute = aSYSTEM | aHIDDEN;
  1642.   pstring mget_mask;
  1643.   fstring buf;
  1644.   char *p=buf;
  1645.  
  1646.   *mget_mask = 0;
  1647.  
  1648.   if (recurse)
  1649.     attribute |= aDIR;
  1650.  
  1651.   abort_mget = False;
  1652.  
  1653.   while (next_token(NULL,p,NULL))
  1654.     {
  1655.       strcpy(mget_mask,cur_dir);
  1656.       if(mget_mask[strlen(mget_mask)-1]!='\\')
  1657.     strcat(mget_mask,"\\");
  1658.  
  1659.       if (*p == '\\')
  1660.     strcpy(mget_mask,p);
  1661.       else
  1662.     strcat(mget_mask,p);
  1663.       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
  1664.     }
  1665.  
  1666.   if (! *mget_mask)
  1667.     {
  1668.       strcpy(mget_mask,cur_dir);
  1669.       if(mget_mask[strlen(mget_mask)-1]!='\\')
  1670.     strcat(mget_mask,"\\");
  1671.       strcat(mget_mask,"*.*");
  1672.       do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False);
  1673.     }
  1674. }
  1675.  
  1676. /****************************************************************************
  1677. make a directory of name "name"
  1678. ****************************************************************************/
  1679. static BOOL do_mkdir(char *name)
  1680. {
  1681.   char *p;
  1682.   char *inbuf,*outbuf;
  1683.  
  1684.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1685.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1686.  
  1687.   if (!inbuf || !outbuf)
  1688.     {
  1689.       DEBUG(0,("out of memory\n"));
  1690.       return False;
  1691.     }
  1692.  
  1693.   bzero(outbuf,smb_size);
  1694.   set_message(outbuf,0,2 + strlen(name),True);
  1695.   
  1696.   CVAL(outbuf,smb_com) = SMBmkdir;
  1697.   SSVAL(outbuf,smb_tid,cnum);
  1698.   setup_pkt(outbuf);
  1699.  
  1700.   
  1701.   p = smb_buf(outbuf);
  1702.   *p++ = 4;      
  1703.   strcpy(p,name);
  1704.   
  1705.   send_smb(Client,outbuf);
  1706.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1707.   
  1708.   if (CVAL(inbuf,smb_rcls) != 0)
  1709.     {
  1710.       DEBUG(0,("%s making remote directory %s\n",
  1711.            smb_errstr(inbuf),CNV_LANG(name)));
  1712.  
  1713.       free(inbuf);free(outbuf);
  1714.       return(False);
  1715.     }
  1716.  
  1717.   free(inbuf);free(outbuf);
  1718.   return(True);
  1719. }
  1720.  
  1721.  
  1722. /****************************************************************************
  1723.   make a directory
  1724.   ****************************************************************************/
  1725. static void cmd_mkdir(char *inbuf,char *outbuf)
  1726. {
  1727.   pstring mask;
  1728.   fstring buf;
  1729.   char *p=buf;
  1730.   
  1731.   strcpy(mask,cur_dir);
  1732.  
  1733.   if (!next_token(NULL,p,NULL))
  1734.     {
  1735.       if (!recurse)
  1736.     DEBUG(0,("mkdir <dirname>\n"));
  1737.       return;
  1738.     }
  1739.   strcat(mask,p);
  1740.  
  1741.   if (recurse)
  1742.     {
  1743.       pstring ddir;
  1744.       pstring ddir2;
  1745.       *ddir2 = 0;
  1746.  
  1747.       strcpy(ddir,mask);
  1748.       trim_string(ddir,".",NULL);
  1749.       p = strtok(ddir,"/\\");
  1750.       while (p)
  1751.     {
  1752.       strcat(ddir2,p);
  1753.       if (!chkpath(ddir2,False))
  1754.         {          
  1755.           do_mkdir(ddir2);
  1756.         }
  1757.       strcat(ddir2,"\\");
  1758.       p = strtok(NULL,"/\\");
  1759.     }     
  1760.     }
  1761.   else
  1762.     do_mkdir(mask);
  1763. }
  1764.  
  1765.  
  1766. /*******************************************************************
  1767.   write to a file using writebraw
  1768.   ********************************************************************/
  1769. static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
  1770. {
  1771.   extern int Client;
  1772.   pstring inbuf;
  1773.  
  1774.   bzero(outbuf,smb_size);
  1775.   bzero(inbuf,smb_size);  
  1776.   set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True);
  1777.  
  1778.   CVAL(outbuf,smb_com) = SMBwritebraw;
  1779.   SSVAL(outbuf,smb_tid,cnum);
  1780.   setup_pkt(outbuf);
  1781.  
  1782.   SSVAL(outbuf,smb_vwv0,fnum);
  1783.   SSVAL(outbuf,smb_vwv1,n);
  1784.   SIVAL(outbuf,smb_vwv3,pos);
  1785.   SSVAL(outbuf,smb_vwv7,1);
  1786.  
  1787.   send_smb(Client,outbuf);
  1788.   
  1789.   if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  1790.     return(0);
  1791.  
  1792.   _smb_setlen(buf-4,n);        /* HACK! XXXX */
  1793.  
  1794.   if (write_socket(Client,buf-4,n+4) != n+4)
  1795.     return(0);
  1796.  
  1797.   if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) {
  1798.     DEBUG(0,("Error writing remote file (2)\n"));
  1799.     return(0);
  1800.   }
  1801.   return(SVAL(inbuf,smb_vwv0));
  1802. }
  1803.       
  1804.  
  1805.  
  1806. /*******************************************************************
  1807.   write to a file
  1808.   ********************************************************************/
  1809. static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
  1810. {
  1811.   pstring inbuf;
  1812.  
  1813.   if (writebraw_supported && n > (max_xmit-200)) 
  1814.     return(smb_writeraw(outbuf,fnum,pos,buf,n));
  1815.  
  1816.   bzero(outbuf,smb_size);
  1817.   bzero(inbuf,smb_size);
  1818.   set_message(outbuf,5,n + 3,True);
  1819.  
  1820.   CVAL(outbuf,smb_com) = SMBwrite;
  1821.   SSVAL(outbuf,smb_tid,cnum);
  1822.   setup_pkt(outbuf);
  1823.  
  1824.   SSVAL(outbuf,smb_vwv0,fnum);
  1825.   SSVAL(outbuf,smb_vwv1,n);
  1826.   SIVAL(outbuf,smb_vwv2,pos);
  1827.   SSVAL(outbuf,smb_vwv4,0);
  1828.   CVAL(smb_buf(outbuf),0) = 1;
  1829.   SSVAL(smb_buf(outbuf),1,n);
  1830.  
  1831.   memcpy(smb_buf(outbuf)+3,buf,n);
  1832.  
  1833.   send_smb(Client,outbuf);
  1834.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1835.  
  1836.   if (CVAL(inbuf,smb_rcls) != 0) {
  1837.     DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf)));
  1838.     return(0);
  1839.   }
  1840.   return(SVAL(inbuf,smb_vwv0));
  1841. }
  1842.       
  1843.  
  1844.  
  1845. /****************************************************************************
  1846.   put a single file
  1847.   ****************************************************************************/
  1848. static void do_put(char *rname,char *lname,file_info *finfo)
  1849. {
  1850.   int fnum;
  1851.   FILE *f;
  1852.   int nread=0;
  1853.   char *p;
  1854.   char *inbuf,*outbuf; 
  1855.   time_t close_time = finfo->mtime;
  1856.   char *buf=NULL;
  1857.   static int maxwrite=0;
  1858.  
  1859.   struct timeval tp_start;
  1860.   GetTimeOfDay(&tp_start);
  1861.  
  1862.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1863.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  1864.  
  1865.   if (!inbuf || !outbuf)
  1866.     {
  1867.       DEBUG(0,("out of memory\n"));
  1868.       return;
  1869.     }
  1870.  
  1871.   bzero(outbuf,smb_size);
  1872.   set_message(outbuf,3,2 + strlen(rname),True);
  1873.  
  1874.   if (finfo->mtime == 0 || finfo->mtime == -1)
  1875.     finfo->mtime = finfo->atime = finfo->ctime = time(NULL);
  1876.  
  1877.   CVAL(outbuf,smb_com) = SMBcreate;
  1878.   SSVAL(outbuf,smb_tid,cnum);
  1879.   setup_pkt(outbuf);
  1880.  
  1881.   SSVAL(outbuf,smb_vwv0,finfo->mode);
  1882.   put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
  1883.   
  1884.   p = smb_buf(outbuf);
  1885.   *p++ = 4;      
  1886.   strcpy(p,rname);
  1887.   
  1888.   send_smb(Client,outbuf);
  1889.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1890.   
  1891.   if (CVAL(inbuf,smb_rcls) != 0)
  1892.     {
  1893.       DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1894.  
  1895.       free(inbuf);free(outbuf);if (buf) free(buf);
  1896.       return;
  1897.     }
  1898.  
  1899.   f = fopen(lname,"r");
  1900.  
  1901.   if (!f)
  1902.     {
  1903.       DEBUG(0,("Error opening local file %s\n",lname));
  1904.       free(inbuf);free(outbuf);
  1905.       return;
  1906.     }
  1907.  
  1908.   
  1909.   fnum = SVAL(inbuf,smb_vwv0);
  1910.   if (finfo->size < 0)
  1911.     finfo->size = file_size(lname);
  1912.   
  1913.   DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname)));
  1914.   
  1915.   if (!maxwrite)
  1916.     maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200);
  1917.  
  1918.   while (nread < finfo->size)
  1919.     {
  1920.       int n = maxwrite;
  1921.       int ret;
  1922.  
  1923.       n = MIN(n,finfo->size - nread);
  1924.  
  1925.       buf = (char *)Realloc(buf,n+4);
  1926.   
  1927.       fseek(f,nread,SEEK_SET);
  1928.       if ((n = readfile(buf+4,1,n,f)) < 1)
  1929.     {
  1930.       DEBUG(0,("Error reading local file\n"));
  1931.       break;
  1932.     }      
  1933.  
  1934.       ret = smb_writefile(outbuf,fnum,nread,buf+4,n);
  1935.  
  1936.       if (n != ret) {
  1937.     if (!maxwrite) {
  1938.       DEBUG(0,("Error writing file\n"));
  1939.       break;
  1940.     } else {
  1941.       maxwrite /= 2;
  1942.       continue;
  1943.     }
  1944.       }
  1945.  
  1946.       nread += n;
  1947.     }
  1948.  
  1949.  
  1950.  
  1951.   bzero(outbuf,smb_size);
  1952.   set_message(outbuf,3,0,True);
  1953.   CVAL(outbuf,smb_com) = SMBclose;
  1954.   SSVAL(outbuf,smb_tid,cnum);
  1955.   setup_pkt(outbuf);
  1956.  
  1957.   SSVAL(outbuf,smb_vwv0,fnum);  
  1958.   put_dos_date3(outbuf,smb_vwv1,close_time);
  1959.  
  1960.   send_smb(Client,outbuf);
  1961.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  1962.   
  1963.   if (CVAL(inbuf,smb_rcls) != 0)
  1964.     {
  1965.       DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  1966.       fclose(f);
  1967.       free(inbuf);free(outbuf);
  1968.       if (buf) free(buf);
  1969.       return;
  1970.     }
  1971.  
  1972.   
  1973.   fclose(f);
  1974.   free(inbuf);free(outbuf);
  1975.   if (buf) free(buf);
  1976.  
  1977.   {
  1978.     struct timeval tp_end;
  1979.     int this_time;
  1980.  
  1981.     GetTimeOfDay(&tp_end);
  1982.     this_time = 
  1983.       (tp_end.tv_sec - tp_start.tv_sec)*1000 +
  1984.     (tp_end.tv_usec - tp_start.tv_usec)/1000;
  1985.     put_total_time_ms += this_time;
  1986.     put_total_size += finfo->size;
  1987.  
  1988.     DEBUG(2,("(%g kb/s) (average %g kb/s)\n",
  1989.          finfo->size / (1.024*this_time + 1.0e-4),
  1990.          put_total_size / (1.024*put_total_time_ms)));
  1991.   }
  1992.  
  1993.  
  1994.  
  1995. /****************************************************************************
  1996.   put a file
  1997.   ****************************************************************************/
  1998. static void cmd_put(void)
  1999. {
  2000.   pstring lname;
  2001.   pstring rname;
  2002.   fstring buf;
  2003.   char *p=buf;
  2004.   file_info finfo;
  2005.   finfo = def_finfo;
  2006.   
  2007.   strcpy(rname,cur_dir);
  2008.   strcat(rname,"\\");
  2009.   
  2010.   
  2011.   if (!next_token(NULL,p,NULL))
  2012.     {
  2013.       DEBUG(0,("put <filename>\n"));
  2014.       return;
  2015.     }
  2016.   strcpy(lname,p);
  2017.   
  2018.   if (next_token(NULL,p,NULL))
  2019.     strcat(rname,p);      
  2020.   else
  2021.     strcat(rname,lname);
  2022.  
  2023.   dos_clean_name(rname);
  2024.  
  2025.   {
  2026.     struct stat st;
  2027.     if (!file_exist(lname,&st)) {
  2028.       DEBUG(0,("%s does not exist\n",lname));
  2029.       return;
  2030.     }
  2031.     finfo.mtime = st.st_mtime;
  2032.   }
  2033.  
  2034.   do_put(rname,lname,&finfo);
  2035. }
  2036.  
  2037. /****************************************************************************
  2038.   seek in a directory/file list until you get something that doesn't start with
  2039.   the specified name
  2040.   ****************************************************************************/
  2041. static BOOL seek_list(FILE *f,char *name)
  2042. {
  2043.   pstring s;
  2044.   while (!feof(f))
  2045.     {
  2046.       if (fscanf(f,"%s",s) != 1) return(False);
  2047.       trim_string(s,"./",NULL);
  2048.       if (strncmp(s,name,strlen(name)) != 0)
  2049.     {
  2050.       strcpy(name,s);
  2051.       return(True);
  2052.     }
  2053.     }
  2054.       
  2055.   return(False);
  2056. }
  2057.  
  2058.  
  2059. /****************************************************************************
  2060.   set the file selection mask
  2061.   ****************************************************************************/
  2062. static void cmd_select(void)
  2063. {
  2064.   strcpy(fileselection,"");
  2065.   next_token(NULL,fileselection,NULL);
  2066. }
  2067.  
  2068.  
  2069. /****************************************************************************
  2070.   mput some files
  2071.   ****************************************************************************/
  2072. static void cmd_mput(void)
  2073. {
  2074.   pstring lname;
  2075.   pstring rname;
  2076.   file_info finfo;
  2077.   fstring buf;
  2078.   char *p=buf;
  2079.  
  2080.   finfo = def_finfo;
  2081.  
  2082.   
  2083.   while (next_token(NULL,p,NULL))
  2084.     {
  2085.       struct stat st;
  2086.       pstring cmd;
  2087.       pstring tmpname;
  2088.       FILE *f;
  2089.       
  2090.       sprintf(tmpname,"/tmp/ls.smb.%d",(int)getpid());
  2091.       if (recurse)
  2092.     sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname);
  2093.       else
  2094.     sprintf(cmd,"/bin/ls %s > %s",p,tmpname);
  2095.       system(cmd);
  2096.  
  2097.       f = fopen(tmpname,"r");
  2098.       if (!f) continue;
  2099.  
  2100.       while (!feof(f))
  2101.     {
  2102.       pstring quest;
  2103.  
  2104.       if (fscanf(f,"%s",lname) != 1) break;
  2105.       trim_string(lname,"./",NULL);
  2106.  
  2107.     again1:
  2108.  
  2109.       /* check if it's a directory */
  2110.       if (directory_exist(lname,&st))
  2111.         {
  2112.           if (!recurse) continue;
  2113.           sprintf(quest,"Put directory %s? ",lname);
  2114.           if (prompt && !yesno(quest)) 
  2115.         {
  2116.           strcat(lname,"/");
  2117.           if (!seek_list(f,lname))
  2118.             break;
  2119.           goto again1;            
  2120.         }
  2121.           
  2122.           strcpy(rname,cur_dir);
  2123.           strcat(rname,lname);
  2124.           if (!do_mkdir(rname))
  2125.         {
  2126.           strcat(lname,"/");
  2127.           if (!seek_list(f,lname))
  2128.             break;
  2129.           goto again1;                      
  2130.         }
  2131.  
  2132.           continue;
  2133.         }
  2134.       else
  2135.         {
  2136.           sprintf(quest,"Put file %s? ",lname);
  2137.           if (prompt && !yesno(quest)) continue;
  2138.  
  2139.           strcpy(rname,cur_dir);
  2140.           strcat(rname,lname);
  2141.         }
  2142.       dos_format(rname);
  2143.  
  2144.       /* null size so do_put knows to ignore it */
  2145.       finfo.size = -1;
  2146.  
  2147.       /* set the date on the file */
  2148.       finfo.mtime = st.st_mtime;
  2149.  
  2150.       do_put(rname,lname,&finfo);
  2151.     }
  2152.       fclose(f);
  2153.       unlink(tmpname);
  2154.     }
  2155. }
  2156.  
  2157. /****************************************************************************
  2158.   cancel a print job
  2159.   ****************************************************************************/
  2160. static void do_cancel(int job)
  2161. {
  2162.   char *rparam = NULL;
  2163.   char *rdata = NULL;
  2164.   char *p;
  2165.   int rdrcnt,rprcnt;
  2166.   pstring param;
  2167.  
  2168.   bzero(param,sizeof(param));
  2169.  
  2170.   p = param;
  2171.   SSVAL(p,0,81);        /* api number */
  2172.   p += 2;
  2173.   strcpy(p,"W");
  2174.   p = skip_string(p,1);
  2175.   strcpy(p,"");
  2176.   p = skip_string(p,1);
  2177.   SSVAL(p,0,job);     
  2178.   p += 2;
  2179.  
  2180.   if (call_api(PTR_DIFF(p,param),0,
  2181.            6,1000,
  2182.            &rprcnt,&rdrcnt,
  2183.            param,NULL,
  2184.            &rparam,&rdata))
  2185.     {
  2186.       int res = SVAL(rparam,0);
  2187.  
  2188.       if (!res)
  2189.     printf("Job %d cancelled\n",job);
  2190.       else
  2191.     printf("Error %d calcelling job %d\n",res,job);
  2192.       return;
  2193.     }
  2194.   else
  2195.   printf("Server refused cancel request\n");
  2196.  
  2197.   if (rparam) free(rparam);
  2198.   if (rdata) free(rdata);
  2199.  
  2200.   return;
  2201. }
  2202.  
  2203.  
  2204. /****************************************************************************
  2205.   cancel a print job
  2206.   ****************************************************************************/
  2207. static void cmd_cancel(char *inbuf,char *outbuf )
  2208. {
  2209.   fstring buf;
  2210.   int job; 
  2211.  
  2212.   if (!connect_as_printer)
  2213.     {
  2214.       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
  2215.       DEBUG(0,("Trying to cancel print jobs without -P may fail\n"));
  2216.     }
  2217.  
  2218.   if (!next_token(NULL,buf,NULL)) {
  2219.     printf("cancel <jobid> ...\n");
  2220.     return;
  2221.   }
  2222.   do {
  2223.     job = atoi(buf);
  2224.     do_cancel(job);
  2225.   } while (next_token(NULL,buf,NULL));
  2226. }
  2227.  
  2228.  
  2229. /****************************************************************************
  2230.   get info on a file
  2231.   ****************************************************************************/
  2232. static void cmd_stat(char *inbuf,char *outbuf)
  2233. {
  2234.   fstring buf;
  2235.   pstring param;
  2236.   char *resp_data=NULL;
  2237.   char *resp_param=NULL;
  2238.   int resp_data_len = 0;
  2239.   int resp_param_len=0;
  2240.   char *p;
  2241.   uint16 setup = TRANSACT2_QPATHINFO;
  2242.  
  2243.   if (!next_token(NULL,buf,NULL)) {
  2244.     printf("stat <file>\n");
  2245.     return;
  2246.   }
  2247.  
  2248.   bzero(param,6);
  2249.   SSVAL(param,0,4); /* level */
  2250.   p = param+6;
  2251.   strcpy(p,cur_dir);
  2252.   strcat(p,buf);
  2253.  
  2254.   send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
  2255.              NULL,param,&setup,
  2256.              0,6 + strlen(p)+1,1,
  2257.              BUFFER_SIZE,2,0);
  2258.  
  2259.   receive_trans_response(inbuf,SMBtrans2,
  2260.               &resp_data_len,&resp_param_len,
  2261.               &resp_data,&resp_param);
  2262.  
  2263.   if (resp_data) free(resp_data); resp_data = NULL;
  2264.   if (resp_param) free(resp_param); resp_param = NULL;
  2265. }
  2266.  
  2267.  
  2268. /****************************************************************************
  2269.   print a file
  2270.   ****************************************************************************/
  2271. static void cmd_print(char *inbuf,char *outbuf )
  2272. {
  2273.   int fnum;
  2274.   FILE *f = NULL;
  2275.   uint32 nread=0;
  2276.   pstring lname;
  2277.   pstring rname;
  2278.   char *p;
  2279.  
  2280.   if (!connect_as_printer)
  2281.     {
  2282.       DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
  2283.       DEBUG(0,("Trying to print without -P may fail\n"));
  2284.     }
  2285.  
  2286.   if (!next_token(NULL,lname,NULL))
  2287.     {
  2288.       DEBUG(0,("print <filename>\n"));
  2289.       return;
  2290.     }
  2291.  
  2292.   strcpy(rname,lname);
  2293.   p = strrchr(rname,'/');
  2294.   if (p)
  2295.     {
  2296.       pstring tname;
  2297.       strcpy(tname,p+1);
  2298.       strcpy(rname,tname);
  2299.     }
  2300.  
  2301.   if ((int)strlen(rname) > 14)
  2302.     rname[14] = 0;
  2303.  
  2304.   if (strequal(lname,"-"))
  2305.     {
  2306.       f = stdin;
  2307.       strcpy(rname,"stdin");
  2308.     }
  2309.   
  2310.   dos_clean_name(rname);
  2311.  
  2312.   bzero(outbuf,smb_size);
  2313.   set_message(outbuf,2,2 + strlen(rname),True);
  2314.   
  2315.   CVAL(outbuf,smb_com) = SMBsplopen;
  2316.   SSVAL(outbuf,smb_tid,cnum);
  2317.   setup_pkt(outbuf);
  2318.  
  2319.   SSVAL(outbuf,smb_vwv0,0);
  2320.   SSVAL(outbuf,smb_vwv1,printmode);
  2321.   
  2322.   p = smb_buf(outbuf);
  2323.   *p++ = 4;      
  2324.   strcpy(p,rname);
  2325.   
  2326.   send_smb(Client,outbuf);
  2327.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2328.   
  2329.   if (CVAL(inbuf,smb_rcls) != 0)
  2330.     {
  2331.       DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname)));
  2332.       return;
  2333.     }
  2334.   
  2335.   if (!f)
  2336.     f = fopen(lname,"r");
  2337.   if (!f)
  2338.     {
  2339.       DEBUG(0,("Error opening local file %s\n",lname));
  2340.       return;
  2341.     }
  2342.  
  2343.   
  2344.   fnum = SVAL(inbuf,smb_vwv0);
  2345.   
  2346.   DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname)));
  2347.   
  2348.   while (!feof(f))
  2349.     {
  2350.       int n;
  2351.   
  2352.       bzero(outbuf,smb_size);
  2353.       set_message(outbuf,1,3,True);
  2354.  
  2355.       /* for some strange reason the OS/2 print server can't handle large
  2356.      packets when printing. weird */
  2357.       n = MIN(1024,max_xmit-(smb_len(outbuf)+4));
  2358.  
  2359.       if (translation)
  2360.     n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n));
  2361.       else
  2362.     n = readfile(smb_buf(outbuf)+3,1,n,f);
  2363.       if (n <= 0) 
  2364.     {
  2365.       DEBUG(0,("read gave %d\n",n));
  2366.       break;
  2367.     }
  2368.  
  2369.       smb_setlen(outbuf,smb_len(outbuf) + n);
  2370.  
  2371.       CVAL(outbuf,smb_com) = SMBsplwr;
  2372.       SSVAL(outbuf,smb_tid,cnum);
  2373.       setup_pkt(outbuf);
  2374.  
  2375.       SSVAL(outbuf,smb_vwv0,fnum);
  2376.       SSVAL(outbuf,smb_vwv1,n+3);
  2377.       CVAL(smb_buf(outbuf),0) = 1;
  2378.       SSVAL(smb_buf(outbuf),1,n);
  2379.  
  2380.       send_smb(Client,outbuf);
  2381.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2382.  
  2383.       if (CVAL(inbuf,smb_rcls) != 0)
  2384.     {
  2385.       DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf)));
  2386.       break;
  2387.     }
  2388.  
  2389.       nread += n;
  2390.     }
  2391.  
  2392.   DEBUG(2,("%d bytes printed\n",nread));
  2393.  
  2394.   bzero(outbuf,smb_size);
  2395.   set_message(outbuf,1,0,True);
  2396.   CVAL(outbuf,smb_com) = SMBsplclose;
  2397.   SSVAL(outbuf,smb_tid,cnum);
  2398.   setup_pkt(outbuf);
  2399.  
  2400.   SSVAL(outbuf,smb_vwv0,fnum);
  2401.  
  2402.   send_smb(Client,outbuf);
  2403.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2404.   
  2405.   if (CVAL(inbuf,smb_rcls) != 0)
  2406.     {
  2407.       DEBUG(0,("%s closing print file\n",smb_errstr(inbuf)));
  2408.       if (f != stdin)
  2409.     fclose(f);
  2410.       return;
  2411.     }
  2412.  
  2413.   if (f != stdin)
  2414.     fclose(f);
  2415. }
  2416.  
  2417. /****************************************************************************
  2418. print a file
  2419. ****************************************************************************/
  2420. static void cmd_queue(char *inbuf,char *outbuf )
  2421. {
  2422.   int count;
  2423.   char *p;
  2424.  
  2425.   bzero(outbuf,smb_size);
  2426.   set_message(outbuf,2,0,True);
  2427.   
  2428.   CVAL(outbuf,smb_com) = SMBsplretq;
  2429.   SSVAL(outbuf,smb_tid,cnum);
  2430.   setup_pkt(outbuf);
  2431.  
  2432.   SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
  2433.   SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
  2434.   
  2435.   send_smb(Client,outbuf);
  2436.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2437.   
  2438.   if (CVAL(inbuf,smb_rcls) != 0)
  2439.     {
  2440.       DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf)));
  2441.       return;
  2442.     }
  2443.  
  2444.   count = SVAL(inbuf,smb_vwv0);
  2445.   p = smb_buf(inbuf) + 3;
  2446.   if (count <= 0)
  2447.     {
  2448.       DEBUG(0,("No entries in the print queue\n"));
  2449.       return;
  2450.     }  
  2451.  
  2452.   {
  2453.     char status[20];
  2454.  
  2455.     DEBUG(0,("Job      Name              Size         Status\n"));
  2456.  
  2457.     while (count--)
  2458.       {
  2459.     switch (CVAL(p,4))
  2460.       {
  2461.       case 0x01: sprintf(status,"held or stopped"); break;
  2462.       case 0x02: sprintf(status,"printing"); break;
  2463.       case 0x03: sprintf(status,"awaiting print"); break;
  2464.       case 0x04: sprintf(status,"in intercept"); break;
  2465.       case 0x05: sprintf(status,"file had error"); break;
  2466.       case 0x06: sprintf(status,"printer error"); break;
  2467.       default: sprintf(status,"unknown"); break;
  2468.       }
  2469.  
  2470.     DEBUG(0,("%-6d   %-16.16s  %-9d    %s\n",
  2471.          SVAL(p,5),p+12,IVAL(p,7),status));
  2472.     p += 28;
  2473.       }
  2474.   }
  2475.   
  2476. }
  2477.  
  2478.  
  2479. /****************************************************************************
  2480. delete some files
  2481. ****************************************************************************/
  2482. static void do_del(file_info *finfo)
  2483. {
  2484.   char *p;
  2485.   char *inbuf,*outbuf;
  2486.   pstring mask;
  2487.  
  2488.   strcpy(mask,cur_dir);
  2489.   strcat(mask,finfo->name);
  2490.  
  2491.   if (finfo->mode & aDIR) 
  2492.     return;
  2493.  
  2494.   inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2495.   outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2496.   
  2497.   if (!inbuf || !outbuf)
  2498.     {
  2499.       DEBUG(0,("out of memory\n"));
  2500.       return;
  2501.     }
  2502.  
  2503.   bzero(outbuf,smb_size);
  2504.   set_message(outbuf,1,2 + strlen(mask),True);
  2505.   
  2506.   CVAL(outbuf,smb_com) = SMBunlink;
  2507.   SSVAL(outbuf,smb_tid,cnum);
  2508.   setup_pkt(outbuf);
  2509.  
  2510.   SSVAL(outbuf,smb_vwv0,0);
  2511.   
  2512.   p = smb_buf(outbuf);
  2513.   *p++ = 4;      
  2514.   strcpy(p,mask);
  2515.   
  2516.   send_smb(Client,outbuf);
  2517.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2518.   
  2519.   if (CVAL(inbuf,smb_rcls) != 0)
  2520.     DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2521.  
  2522.   free(inbuf);free(outbuf);
  2523.   
  2524. }
  2525.  
  2526. /****************************************************************************
  2527. delete some files
  2528. ****************************************************************************/
  2529. static void cmd_del(char *inbuf,char *outbuf )
  2530. {
  2531.   pstring mask;
  2532.   fstring buf;
  2533.   int attribute = aSYSTEM | aHIDDEN;
  2534.  
  2535.   if (recurse)
  2536.     attribute |= aDIR;
  2537.   
  2538.   strcpy(mask,cur_dir);
  2539.     
  2540.   if (!next_token(NULL,buf,NULL))
  2541.     {
  2542.       DEBUG(0,("del <filename>\n"));
  2543.       return;
  2544.     }
  2545.   strcat(mask,buf);
  2546.  
  2547.   do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False);
  2548. }
  2549.  
  2550.  
  2551. /****************************************************************************
  2552. remove a directory
  2553. ****************************************************************************/
  2554. static void cmd_rmdir(char *inbuf,char *outbuf )
  2555. {
  2556.   pstring mask;
  2557.   fstring buf;
  2558.   char *p;
  2559.   
  2560.   strcpy(mask,cur_dir);
  2561.   
  2562.   if (!next_token(NULL,buf,NULL))
  2563.     {
  2564.       DEBUG(0,("rmdir <dirname>\n"));
  2565.       return;
  2566.     }
  2567.   strcat(mask,buf);
  2568.  
  2569.   bzero(outbuf,smb_size);
  2570.   set_message(outbuf,0,2 + strlen(mask),True);
  2571.   
  2572.   CVAL(outbuf,smb_com) = SMBrmdir;
  2573.   SSVAL(outbuf,smb_tid,cnum);
  2574.   setup_pkt(outbuf);
  2575.  
  2576.   
  2577.   p = smb_buf(outbuf);
  2578.   *p++ = 4;      
  2579.   strcpy(p,mask);
  2580.   
  2581.   send_smb(Client,outbuf);
  2582.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2583.   
  2584.   if (CVAL(inbuf,smb_rcls) != 0)
  2585.     {
  2586.       DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask)));
  2587.       return;
  2588.     }
  2589.   
  2590. }
  2591.  
  2592. /****************************************************************************
  2593. rename some files
  2594. ****************************************************************************/
  2595. static void cmd_rename(char *inbuf,char *outbuf )
  2596. {
  2597.   pstring src,dest;
  2598.   fstring buf,buf2;
  2599.   char *p;
  2600.   
  2601.   strcpy(src,cur_dir);
  2602.   strcpy(dest,cur_dir);
  2603.   
  2604.   if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL))
  2605.     {
  2606.       DEBUG(0,("rename <src> <dest>\n"));
  2607.       return;
  2608.     }
  2609.   strcat(src,buf);
  2610.   strcat(dest,buf2);
  2611.  
  2612.   bzero(outbuf,smb_size);
  2613.   set_message(outbuf,1,4 + strlen(src) + strlen(dest),True);
  2614.   
  2615.   CVAL(outbuf,smb_com) = SMBmv;
  2616.   SSVAL(outbuf,smb_tid,cnum);
  2617.   SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
  2618.   setup_pkt(outbuf);
  2619.   
  2620.   p = smb_buf(outbuf);
  2621.   *p++ = 4;      
  2622.   strcpy(p,src);
  2623.   p = skip_string(p,1);
  2624.   *p++ = 4;      
  2625.   strcpy(p,dest);
  2626.   
  2627.   send_smb(Client,outbuf);
  2628.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2629.   
  2630.   if (CVAL(inbuf,smb_rcls) != 0)
  2631.     {
  2632.       DEBUG(0,("%s renaming files\n",smb_errstr(inbuf)));
  2633.       return;
  2634.     }
  2635.   
  2636. }
  2637.  
  2638.  
  2639. /****************************************************************************
  2640. toggle the prompt flag
  2641. ****************************************************************************/
  2642. static void cmd_prompt(void)
  2643. {
  2644.   prompt = !prompt;
  2645.   DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
  2646. }
  2647.  
  2648.  
  2649. /****************************************************************************
  2650. set the newer than time
  2651. ****************************************************************************/
  2652. static void cmd_newer(void)
  2653. {
  2654.   fstring buf;
  2655.   BOOL ok;
  2656.   struct stat sbuf;
  2657.  
  2658.   ok = next_token(NULL,buf,NULL);
  2659.   if (ok && (sys_stat(buf,&sbuf) == 0))
  2660.     {
  2661.       newer_than = sbuf.st_mtime;
  2662.       DEBUG(1,("Getting files newer than %s",
  2663.            asctime(LocalTime(&newer_than,GMT_TO_LOCAL))));
  2664.     }
  2665.   else
  2666.     newer_than = 0;
  2667.  
  2668.   if (ok && newer_than == 0)
  2669.     DEBUG(0,("Error setting newer-than time\n"));
  2670. }
  2671.  
  2672. /****************************************************************************
  2673. set the archive level
  2674. ****************************************************************************/
  2675. static void cmd_archive(void)
  2676. {
  2677.   fstring buf;
  2678.  
  2679.   if (next_token(NULL,buf,NULL)) {
  2680.     archive_level = atoi(buf);
  2681.   } else
  2682.     DEBUG(0,("Archive level is %d\n",archive_level));
  2683. }
  2684.  
  2685. /****************************************************************************
  2686. toggle the lowercaseflag
  2687. ****************************************************************************/
  2688. static void cmd_lowercase(void)
  2689. {
  2690.   lowercase = !lowercase;
  2691.   DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
  2692. }
  2693.  
  2694.  
  2695.  
  2696.  
  2697. /****************************************************************************
  2698. toggle the recurse flag
  2699. ****************************************************************************/
  2700. static void cmd_recurse(void)
  2701. {
  2702.   recurse = !recurse;
  2703.   DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
  2704. }
  2705.  
  2706. /****************************************************************************
  2707. toggle the translate flag
  2708. ****************************************************************************/
  2709. static void cmd_translate(void)
  2710. {
  2711.   translation = !translation;
  2712.   DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
  2713.     translation?"on":"off"));
  2714. }
  2715.  
  2716.  
  2717. /****************************************************************************
  2718. do a printmode command
  2719. ****************************************************************************/
  2720. static void cmd_printmode(void)
  2721. {
  2722.   fstring buf;
  2723.   fstring mode;
  2724.  
  2725.   if (next_token(NULL,buf,NULL))
  2726.     {
  2727.       if (strequal(buf,"text"))
  2728.     printmode = 0;      
  2729.       else
  2730.     {
  2731.       if (strequal(buf,"graphics"))
  2732.         printmode = 1;
  2733.       else
  2734.         printmode = atoi(buf);
  2735.     }
  2736.     }
  2737.  
  2738.   switch(printmode)
  2739.     {
  2740.     case 0: 
  2741.       strcpy(mode,"text");
  2742.       break;
  2743.     case 1: 
  2744.       strcpy(mode,"graphics");
  2745.       break;
  2746.     default: 
  2747.       sprintf(mode,"%d",printmode);
  2748.       break;
  2749.     }
  2750.  
  2751.   DEBUG(2,("the printmode is now %s\n",mode));
  2752. }
  2753.  
  2754. /****************************************************************************
  2755. do the lcd command
  2756. ****************************************************************************/
  2757. static void cmd_lcd(void)
  2758. {
  2759.   fstring buf;
  2760.   pstring d;
  2761.  
  2762.   if (next_token(NULL,buf,NULL))
  2763.     sys_chdir(buf);
  2764.   DEBUG(2,("the local directory is now %s\n",GetWd(d)));
  2765. }
  2766.  
  2767.  
  2768. /****************************************************************************
  2769. send a session request
  2770. ****************************************************************************/
  2771. static BOOL send_session_request(char *inbuf,char *outbuf)
  2772. {
  2773.   fstring dest;
  2774.   char *p;
  2775.   int len = 4;
  2776.   /* send a session request (RFC 8002) */
  2777.  
  2778.   strcpy(dest,desthost);
  2779.   p = strchr(dest,'.');
  2780.   if (p) *p = 0;
  2781.  
  2782.   /* put in the destination name */
  2783.   p = outbuf+len;
  2784.   name_mangle(dest,p,name_type);
  2785.   len += name_len(p);
  2786.  
  2787.   /* and my name */
  2788.   p = outbuf+len;
  2789.   name_mangle(myname,p,0);
  2790.   len += name_len(p);
  2791.  
  2792.   /* setup the packet length */
  2793.   _smb_setlen(outbuf,len);
  2794.   CVAL(outbuf,0) = 0x81;
  2795.  
  2796.   send_smb(Client,outbuf);
  2797.   DEBUG(5,("Sent session request\n"));
  2798.  
  2799.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2800.  
  2801.   if (CVAL(inbuf,0) == 0x84) /* C. Hoch  9/14/95 Start */
  2802.     {
  2803.       /* For information, here is the response structure.
  2804.        * We do the byte-twiddling to for portability.
  2805.        struct RetargetResponse{
  2806.        unsigned char type;
  2807.        unsigned char flags;
  2808.        int16 length;
  2809.        int32 ip_addr;
  2810.        int16 port;
  2811.        };
  2812.        */
  2813.       extern int Client;
  2814.       int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
  2815.       /* SESSION RETARGET */
  2816.       putip((char *)&dest_ip,inbuf+4);
  2817.  
  2818.       close_sockets();
  2819.       Client = open_socket_out(SOCK_STREAM, &dest_ip, port);
  2820.       if (Client == -1)
  2821.         return False;
  2822.  
  2823.       DEBUG(3,("Retargeted\n"));
  2824.  
  2825.       set_socket_options(Client,user_socket_options);
  2826.  
  2827.       /* Try again */
  2828.       return send_session_request(inbuf,outbuf);
  2829.     } /* C. Hoch 9/14/95 End */
  2830.  
  2831.  
  2832.   if (CVAL(inbuf,0) != 0x82)
  2833.     {
  2834.       int ecode = CVAL(inbuf,4);
  2835.       DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
  2836.            CVAL(inbuf,0),ecode,myname,desthost));
  2837.       switch (ecode)
  2838.     {
  2839.     case 0x80: 
  2840.       DEBUG(0,("Not listening on called name\n")); 
  2841.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  2842.       DEBUG(0,("You may find the -I option useful for this\n"));
  2843.       break;
  2844.     case 0x81: 
  2845.       DEBUG(0,("Not listening for calling name\n")); 
  2846.       DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
  2847.       DEBUG(0,("You may find the -n option useful for this\n"));
  2848.       break;
  2849.     case 0x82: 
  2850.       DEBUG(0,("Called name not present\n")); 
  2851.       DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
  2852.       DEBUG(0,("You may find the -I option useful for this\n"));
  2853.       break;
  2854.     case 0x83: 
  2855.       DEBUG(0,("Called name present, but insufficient resources\n")); 
  2856.       DEBUG(0,("Perhaps you should try again later?\n")); 
  2857.       break;
  2858.     default:
  2859.       DEBUG(0,("Unspecified error 0x%X\n",ecode)); 
  2860.       DEBUG(0,("Your server software is being unfriendly\n"));
  2861.       break;      
  2862.     }
  2863.       return(False);
  2864.     }
  2865.   return(True);
  2866. }
  2867.  
  2868.  
  2869. /****************************************************************************
  2870. send a login command
  2871. ****************************************************************************/
  2872. static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
  2873. {
  2874.   BOOL was_null = (!inbuf && !outbuf);
  2875.   int sesskey=0;
  2876.   time_t servertime = 0;
  2877.   extern int serverzone;
  2878.   int sec_mode=0;
  2879.   int crypt_len;
  2880.   int max_vcs=0;
  2881.   struct {
  2882.     int prot;
  2883.     char *name;
  2884.   }
  2885.   prots[] = 
  2886.     {
  2887.       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
  2888.       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
  2889.       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
  2890.       {PROTOCOL_LANMAN1,"LANMAN1.0"},
  2891.       {PROTOCOL_LANMAN2,"LM1.2X002"},
  2892.       {PROTOCOL_LANMAN2,"Samba"},
  2893.       {PROTOCOL_NT1,"NT LM 0.12"},
  2894.       {PROTOCOL_NT1,"NT LANMAN 1.0"},
  2895.       {-1,NULL}
  2896.     };
  2897.   char *pass = NULL;  
  2898.   pstring dev;
  2899.   char *p;
  2900.   int numprots;
  2901.  
  2902.   if (was_null)
  2903.     {
  2904.       inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2905.       outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  2906.     }
  2907.  
  2908. #if AJT
  2909.   if (strstr(service,"IPC$")) connect_as_ipc = True;
  2910. #endif
  2911.  
  2912.   strcpy(dev,"A:");
  2913.   if (connect_as_printer)
  2914.     strcpy(dev,"LPT1:");
  2915.   if (connect_as_ipc)
  2916.     strcpy(dev,"IPC");
  2917.  
  2918.  
  2919.   if (start_session && !send_session_request(inbuf,outbuf))
  2920.     {
  2921.       if (was_null)
  2922.     {
  2923.       free(inbuf);
  2924.       free(outbuf);
  2925.     }      
  2926.       return(False);
  2927.     }
  2928.  
  2929.   bzero(outbuf,smb_size);
  2930.  
  2931.   /* setup the protocol strings */
  2932.   {
  2933.     int plength;
  2934.  
  2935.     for (plength=0,numprots=0;
  2936.      prots[numprots].name && prots[numprots].prot<=max_protocol;
  2937.      numprots++)
  2938.       plength += strlen(prots[numprots].name)+2;
  2939.     
  2940.     set_message(outbuf,0,plength,True);
  2941.  
  2942.     p = smb_buf(outbuf);
  2943.     for (numprots=0;
  2944.      prots[numprots].name && prots[numprots].prot<=max_protocol;
  2945.      numprots++)
  2946.       {
  2947.     *p++ = 2;
  2948.     strcpy(p,prots[numprots].name);
  2949.     p += strlen(p) + 1;
  2950.       }
  2951.   }
  2952.  
  2953.   CVAL(outbuf,smb_com) = SMBnegprot;
  2954.   setup_pkt(outbuf);
  2955.  
  2956.   CVAL(smb_buf(outbuf),0) = 2;
  2957.  
  2958.   send_smb(Client,outbuf);
  2959.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  2960.  
  2961.   show_msg(inbuf);
  2962.  
  2963.   if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
  2964.     {
  2965.       DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
  2966.         myname,desthost,smb_errstr(inbuf)));
  2967.       if (was_null)
  2968.     {
  2969.       free(inbuf);
  2970.       free(outbuf);
  2971.     }
  2972.       return(False);
  2973.     }
  2974.  
  2975.   Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
  2976.  
  2977.  
  2978.   if (Protocol < PROTOCOL_NT1) {    
  2979.     sec_mode = SVAL(inbuf,smb_vwv1);
  2980.     max_xmit = SVAL(inbuf,smb_vwv2);
  2981.     sesskey = IVAL(inbuf,smb_vwv6);
  2982.     serverzone = SVALS(inbuf,smb_vwv10)*60;
  2983.     /* this time is converted to GMT by make_unix_date */
  2984.     servertime = make_unix_date(inbuf+smb_vwv8);
  2985.     if (Protocol >= PROTOCOL_COREPLUS) {
  2986.       readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
  2987.       writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
  2988.     }
  2989.     crypt_len = smb_buflen(inbuf);
  2990.     memcpy(cryptkey,smb_buf(inbuf),8);
  2991.     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
  2992.     max_vcs = SVAL(inbuf,smb_vwv4); 
  2993.     DEBUG(3,("max vcs %d\n",max_vcs)); 
  2994.     DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
  2995.   } else {
  2996.     /* NT protocol */
  2997.     sec_mode = CVAL(inbuf,smb_vwv1);
  2998.     max_xmit = IVAL(inbuf,smb_vwv3+1);
  2999.     sesskey = IVAL(inbuf,smb_vwv7+1);
  3000.     serverzone = SVALS(inbuf,smb_vwv15+1)*60;
  3001.     /* this time arrives in real GMT */
  3002.     servertime = interpret_long_date(inbuf+smb_vwv11+1);
  3003.     crypt_len = CVAL(inbuf,smb_vwv16+1);
  3004.     memcpy(cryptkey,smb_buf(inbuf),8);
  3005.     if (IVAL(inbuf,smb_vwv9+1) & 1)
  3006.       readbraw_supported = writebraw_supported = True;      
  3007.     DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
  3008.     max_vcs = SVAL(inbuf,smb_vwv2+1); 
  3009.     DEBUG(3,("max vcs %d\n",max_vcs));
  3010.     DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
  3011.     DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
  3012.   }
  3013.  
  3014.   DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
  3015.   DEBUG(3,("max xmt %d\n",max_xmit));
  3016.   DEBUG(3,("Got %d byte crypt key\n",crypt_len));
  3017.   DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
  3018.  
  3019.   doencrypt = ((sec_mode & 2) != 0);
  3020.  
  3021.   if (servertime) {
  3022.     static BOOL done_time = False;
  3023.     if (!done_time) {
  3024.       DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
  3025.            asctime(LocalTime(&servertime,GMT_TO_LOCAL)),
  3026.            -(double)(serverzone/3600.0)));
  3027.       done_time = True;
  3028.     }
  3029.   }
  3030.  
  3031.  get_pass:
  3032.  
  3033.   if (got_pass)
  3034.     pass = password;
  3035.   else
  3036.     pass = (char *)getpass("Password: ");
  3037.  
  3038.   if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
  3039.     {
  3040.       fstring pword;
  3041.       int passlen = strlen(pass)+1;
  3042.       strcpy(pword,pass);      
  3043.  
  3044. #ifdef SMB_PASSWD
  3045.       if (doencrypt && *pass) {
  3046.     DEBUG(3,("Using encrypted passwords\n"));
  3047.     passlen = 24;
  3048.     SMBencrypt(pass,cryptkey,pword);
  3049.       }
  3050. #else
  3051.       doencrypt = False;
  3052. #endif
  3053.  
  3054.       /* if in share level security then don't send a password now */
  3055.       if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} 
  3056.  
  3057.       /* send a session setup command */
  3058.       bzero(outbuf,smb_size);
  3059.  
  3060.       if (Protocol < PROTOCOL_NT1) {
  3061.     set_message(outbuf,10,1 + strlen(username) + passlen,True);
  3062.     CVAL(outbuf,smb_com) = SMBsesssetupX;
  3063.     setup_pkt(outbuf);
  3064.  
  3065.     CVAL(outbuf,smb_vwv0) = 0xFF;
  3066.     SSVAL(outbuf,smb_vwv2,max_xmit);
  3067.     SSVAL(outbuf,smb_vwv3,2);
  3068.     SSVAL(outbuf,smb_vwv4,max_vcs-1);
  3069.     SIVAL(outbuf,smb_vwv5,sesskey);
  3070.     SSVAL(outbuf,smb_vwv7,passlen);
  3071.     p = smb_buf(outbuf);
  3072.     memcpy(p,pword,passlen);
  3073.     p += passlen;
  3074.     strcpy(p,username);
  3075.       } else {
  3076.     if (!doencrypt) passlen--;
  3077.     /* for Win95 */
  3078.     set_message(outbuf,13,0,True);
  3079.     CVAL(outbuf,smb_com) = SMBsesssetupX;
  3080.     setup_pkt(outbuf);
  3081.  
  3082.     CVAL(outbuf,smb_vwv0) = 0xFF;
  3083.     SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
  3084.     SSVAL(outbuf,smb_vwv3,2);
  3085.     SSVAL(outbuf,smb_vwv4,getpid());
  3086.     SIVAL(outbuf,smb_vwv5,sesskey);
  3087.     SSVAL(outbuf,smb_vwv7,passlen);
  3088.     SSVAL(outbuf,smb_vwv8,0);
  3089.     p = smb_buf(outbuf);
  3090.     memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
  3091.     strcpy(p,username);p = skip_string(p,1);
  3092.     strcpy(p,workgroup);p = skip_string(p,1);
  3093.     strcpy(p,"Unix");p = skip_string(p,1);
  3094.     strcpy(p,"Samba");p = skip_string(p,1);
  3095.     set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
  3096.       }
  3097.  
  3098.       send_smb(Client,outbuf);
  3099.       receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  3100.  
  3101.       show_msg(inbuf);
  3102.  
  3103.       if (CVAL(inbuf,smb_rcls) != 0)
  3104.     {
  3105.       if (! *pass &&
  3106.           ((CVAL(inbuf,smb_rcls) == ERRDOS && 
  3107.         SVAL(inbuf,smb_err) == ERRnoaccess) ||
  3108.            (CVAL(inbuf,smb_rcls) == ERRSRV && 
  3109.         SVAL(inbuf,smb_err) == ERRbadpw)))
  3110.         {
  3111.           got_pass = False;
  3112.           DEBUG(3,("resending login\n"));
  3113.           goto get_pass;
  3114.         }
  3115.           
  3116.       DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s   %s\n",
  3117.         username,myname,desthost,smb_errstr(inbuf)));
  3118.       DEBUG(0,("You might find the -U or -n options useful\n"));
  3119.       DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
  3120.       DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
  3121.       if (was_null)
  3122.         {
  3123.           free(inbuf);
  3124.           free(outbuf);
  3125.         }
  3126.       return(False);
  3127.     }
  3128.  
  3129.       if (Protocol >= PROTOCOL_NT1) {
  3130.     char *domain,*os,*lanman;
  3131.     p = smb_buf(inbuf);
  3132.     os = p;
  3133.     lanman = skip_string(os,1);
  3134.     domain = skip_string(lanman,1);
  3135.     if (*domain || *os || *lanman)
  3136.       DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
  3137.       }
  3138.  
  3139.       /* use the returned uid from now on */
  3140.       if (SVAL(inbuf,smb_uid) != uid)
  3141.     DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
  3142.           SVAL(inbuf,smb_uid),uid));
  3143.       uid = SVAL(inbuf,smb_uid);
  3144.     }
  3145.  
  3146.   /* now we've got a connection - send a tcon message */
  3147.   bzero(outbuf,smb_size);
  3148.  
  3149.   if (strncmp(service,"\\\\",2) != 0)
  3150.     {
  3151.       DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
  3152.       DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
  3153.     }
  3154.  
  3155.  
  3156.  again2:
  3157.  
  3158.   {
  3159.     int passlen = strlen(pass)+1;
  3160.     fstring pword;
  3161.     strcpy(pword,pass);
  3162.  
  3163. #ifdef SMB_PASSWD
  3164.     if (doencrypt && *pass) {
  3165.       passlen=24;
  3166.       SMBencrypt(pass,cryptkey,pword);      
  3167.     }
  3168. #endif
  3169.  
  3170.     /* if in user level security then don't send a password now */
  3171.     if ((sec_mode & 1)) {
  3172.       strcpy(pword, ""); passlen=1; 
  3173.     }
  3174.  
  3175.     set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
  3176.     CVAL(outbuf,smb_com) = SMBtconX;
  3177.     setup_pkt(outbuf);
  3178.  
  3179.     SSVAL(outbuf,smb_vwv0,0xFF);
  3180.     SSVAL(outbuf,smb_vwv3,passlen);
  3181.  
  3182.     p = smb_buf(outbuf);
  3183.     memcpy(p,pword,passlen);
  3184.     p += passlen;
  3185.     strcpy(p,service);
  3186.     p = skip_string(p,1);
  3187.     strcpy(p,dev);
  3188.   }
  3189.  
  3190.   send_smb(Client,outbuf);
  3191.   receive_smb(Client,inbuf,CLIENT_TIMEOUT);
  3192.  
  3193.   /* trying again with a blank password */
  3194.   if (CVAL(inbuf,smb_rcls) != 0 && 
  3195.       (int)strlen(pass) > 0 && 
  3196.       !doencrypt &&
  3197.       Protocol >= PROTOCOL_LANMAN1)
  3198.     {
  3199.       DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
  3200.       strcpy(pass,"");
  3201.       goto again2;
  3202.     }  
  3203.  
  3204.   if (CVAL(inbuf,smb_rcls) != 0)
  3205.     {
  3206.       DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
  3207.       DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
  3208.       DEBUG(0,("Some servers insist that these be in uppercase\n"));
  3209.       if (was_null)
  3210.     {
  3211.       free(inbuf);
  3212.       free(outbuf);
  3213.     }
  3214.       return(False);
  3215.     }
  3216.   
  3217.  
  3218.   max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
  3219.   if (max_xmit <= 0)
  3220.     max_xmit = BUFFER_SIZE - 4;
  3221.  
  3222.   cnum = SVAL(inbuf,smb_tid);
  3223.  
  3224.   DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
  3225.  
  3226.   if (was_null)
  3227.     {
  3228.       free(inbuf);
  3229.       free(outbuf);
  3230.     }
  3231.   return True;
  3232. }
  3233.  
  3234.  
  3235. /****************************************************************************
  3236. send a logout command
  3237. ****************************************************************************/
  3238. static void send_logout(void )
  3239. {
  3240.   pstring inbuf,outbuf;
  3241.  
  3242.   bzero(outbuf,smb_size);
  3243.   set_message(outbuf,0,0,True);
  3244.   CVAL(outbuf,smb_com) = SMBtdis;
  3245.   SSVAL(outbuf,smb_tid,cnum);
  3246.   setup_pkt(outbuf);
  3247.  
  3248.   send_smb(Client,outbuf);
  3249.   receive_smb(Client,inbuf,SHORT_TIMEOUT);
  3250.  
  3251.   if (CVAL(inbuf,smb_rcls) != 0)
  3252.     {
  3253.       DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
  3254.     }
  3255.  
  3256.   
  3257. #ifdef STATS
  3258.   stats_report();
  3259. #endif
  3260.   exit(0);
  3261. }
  3262.  
  3263.  
  3264.  
  3265. /****************************************************************************
  3266. call a remote api
  3267. ****************************************************************************/
  3268. static BOOL call_api(int prcnt,int drcnt,
  3269.              int mprcnt,int mdrcnt,
  3270.              int *rprcnt,int *rdrcnt,
  3271.              char *param,char *data,
  3272.              char **rparam,char **rdata)
  3273. {
  3274.   static char *inbuf=NULL;
  3275.   static char *outbuf=NULL;
  3276.  
  3277.   if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3278.   if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3279.  
  3280.   send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
  3281.              data,param,NULL,
  3282.              drcnt,prcnt,0,
  3283.              mdrcnt,mprcnt,0);
  3284.  
  3285.   return (receive_trans_response(inbuf,SMBtrans,
  3286.                                  rdrcnt,rprcnt,
  3287.                                  rdata,rparam));
  3288. }
  3289.  
  3290. /****************************************************************************
  3291.   send a SMB trans or trans2 request
  3292.   ****************************************************************************/
  3293. static BOOL send_trans_request(char *outbuf,int trans,
  3294.                    char *name,int fid,int flags,
  3295.                    char *data,char *param,uint16 *setup,
  3296.                    int ldata,int lparam,int lsetup,
  3297.                    int mdata,int mparam,int msetup)
  3298. {
  3299.   int i;
  3300.   int this_ldata,this_lparam;
  3301.   int tot_data=0,tot_param=0;
  3302.   char *outdata,*outparam;
  3303.   pstring inbuf;
  3304.   char *p;
  3305.  
  3306.   this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
  3307.   this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
  3308.  
  3309.   bzero(outbuf,smb_size);
  3310.   set_message(outbuf,14+lsetup,0,True);
  3311.   CVAL(outbuf,smb_com) = trans;
  3312.   SSVAL(outbuf,smb_tid,cnum);
  3313.   setup_pkt(outbuf);
  3314.  
  3315.   outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
  3316.   outdata = outparam+this_lparam;
  3317.  
  3318.   /* primary request */
  3319.   SSVAL(outbuf,smb_tpscnt,lparam);    /* tpscnt */
  3320.   SSVAL(outbuf,smb_tdscnt,ldata);    /* tdscnt */
  3321.   SSVAL(outbuf,smb_mprcnt,mparam);    /* mprcnt */
  3322.   SSVAL(outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
  3323.   SCVAL(outbuf,smb_msrcnt,msetup);    /* msrcnt */
  3324.   SSVAL(outbuf,smb_flags,flags);    /* flags */
  3325.   SIVAL(outbuf,smb_timeout,0);        /* timeout */
  3326.   SSVAL(outbuf,smb_pscnt,this_lparam);    /* pscnt */
  3327.   SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
  3328.   SSVAL(outbuf,smb_dscnt,this_ldata);    /* dscnt */
  3329.   SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
  3330.   SCVAL(outbuf,smb_suwcnt,lsetup);    /* suwcnt */
  3331.   for (i=0;i<lsetup;i++)        /* setup[] */
  3332.     SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
  3333.   p = smb_buf(outbuf);
  3334.   if (trans==SMBtrans)
  3335.     strcpy(p,name);            /* name[] */
  3336.   else
  3337.     {
  3338.       *p++ = 0;                /* put in a null smb_name */
  3339.       *p++ = 'D'; *p++ = ' ';        /* this was added because OS/2 does it */
  3340.     }
  3341.   if (this_lparam)            /* param[] */
  3342.     memcpy(outparam,param,this_lparam);
  3343.   if (this_ldata)            /* data[] */
  3344.     memcpy(outdata,data,this_ldata);
  3345.   set_message(outbuf,14+lsetup,        /* wcnt, bcc */
  3346.           PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
  3347.  
  3348.   show_msg(outbuf);
  3349.   send_smb(Client,outbuf);
  3350.  
  3351.   if (this_ldata < ldata || this_lparam < lparam)
  3352.     {
  3353.       /* receive interim response */
  3354.       if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
  3355.     {
  3356.       DEBUG(0,("%s request failed (%s)\n",
  3357.                trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
  3358.       return(False);
  3359.     }      
  3360.  
  3361.       tot_data = this_ldata;
  3362.       tot_param = this_lparam;
  3363.  
  3364.       while (tot_data < ldata || tot_param < lparam)
  3365.     {
  3366.       this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
  3367.       this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
  3368.  
  3369.       set_message(outbuf,trans==SMBtrans?8:9,0,True);
  3370.       CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
  3371.  
  3372.       outparam = smb_buf(outbuf);
  3373.       outdata = outparam+this_lparam;
  3374.  
  3375.       /* secondary request */
  3376.       SSVAL(outbuf,smb_tpscnt,lparam);    /* tpscnt */
  3377.       SSVAL(outbuf,smb_tdscnt,ldata);    /* tdscnt */
  3378.       SSVAL(outbuf,smb_spscnt,this_lparam);    /* pscnt */
  3379.       SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
  3380.       SSVAL(outbuf,smb_spsdisp,tot_param);    /* psdisp */
  3381.       SSVAL(outbuf,smb_sdscnt,this_ldata);    /* dscnt */
  3382.       SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
  3383.       SSVAL(outbuf,smb_sdsdisp,tot_data);    /* dsdisp */
  3384.       if (trans==SMBtrans2)
  3385.         SSVAL(outbuf,smb_sfid,fid);        /* fid */
  3386.       if (this_lparam)            /* param[] */
  3387.         memcpy(outparam,param,this_lparam);
  3388.       if (this_ldata)            /* data[] */
  3389.         memcpy(outdata,data,this_ldata);
  3390.       set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
  3391.               PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
  3392.  
  3393.       show_msg(outbuf);
  3394.       send_smb(Client,outbuf);
  3395.  
  3396.       tot_data += this_ldata;
  3397.       tot_param += this_lparam;
  3398.     }
  3399.     }
  3400.  
  3401.     return(True);
  3402. }
  3403.  
  3404. /****************************************************************************
  3405. try and browse available connections on a host
  3406. ****************************************************************************/
  3407. static BOOL browse_host(BOOL sort)
  3408. {
  3409. #ifdef NOSTRCASECMP
  3410. #define strcasecmp StrCaseCmp
  3411. #endif
  3412.   extern int strcasecmp();
  3413.  
  3414.   char *rparam = NULL;
  3415.   char *rdata = NULL;
  3416.   char *p;
  3417.   int rdrcnt,rprcnt;
  3418.   pstring param;
  3419.   int count = -1;
  3420.  
  3421.   /* now send a SMBtrans command with api RNetShareEnum */
  3422.   p = param;
  3423.   SSVAL(p,0,0); /* api number */
  3424.   p += 2;
  3425.   strcpy(p,"WrLeh");
  3426.   p = skip_string(p,1);
  3427.   strcpy(p,"B13BWz");
  3428.   p = skip_string(p,1);
  3429.   SSVAL(p,0,1);
  3430.   SSVAL(p,2,BUFFER_SIZE);
  3431.   p += 4;
  3432.  
  3433.   if (call_api(PTR_DIFF(p,param),0,
  3434.            1024,BUFFER_SIZE,
  3435.                &rprcnt,&rdrcnt,
  3436.            param,NULL,
  3437.            &rparam,&rdata))
  3438.     {
  3439.       int res = SVAL(rparam,0);
  3440.       int converter=SVAL(rparam,2);
  3441.       int i;
  3442.       BOOL long_share_name=False;
  3443.       
  3444.       if (res == 0)
  3445.     {
  3446.       count=SVAL(rparam,4);
  3447.       p = rdata;
  3448.  
  3449.       if (count > 0)
  3450.         {
  3451.           printf("\n\tSharename      Type      Comment\n");
  3452.           printf("\t---------      ----      -------\n");
  3453.         }
  3454.  
  3455.       if (sort)
  3456.         qsort(p,count,20,QSORT_CAST strcasecmp);
  3457.  
  3458.       for (i=0;i<count;i++)
  3459.         {
  3460.           char *sname = p;
  3461.           int type = SVAL(p,14);
  3462.           int comment_offset = IVAL(p,16) & 0xFFFF;
  3463.           fstring typestr;
  3464.           *typestr=0;
  3465.  
  3466.           switch (type)
  3467.         {
  3468.         case STYPE_DISKTREE:
  3469.           strcpy(typestr,"Disk"); break;
  3470.         case STYPE_PRINTQ:
  3471.           strcpy(typestr,"Printer"); break;          
  3472.         case STYPE_DEVICE:
  3473.           strcpy(typestr,"Device"); break;
  3474.         case STYPE_IPC:
  3475.           strcpy(typestr,"IPC"); break;      
  3476.         }
  3477.  
  3478.           printf("\t%-15.15s%-10.10s%s\n",
  3479.              sname,
  3480.              typestr,
  3481.              comment_offset?rdata+comment_offset-converter:"");
  3482.       
  3483.           if (strlen(sname)>8) long_share_name=True;
  3484.       
  3485.           p += 20;
  3486.         }
  3487.  
  3488.       if (long_share_name) {
  3489.         printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n");
  3490.       }
  3491.     }
  3492.     }
  3493.   
  3494.   if (rparam) free(rparam);
  3495.   if (rdata) free(rdata);
  3496.  
  3497.   return(count>0);
  3498. }
  3499.  
  3500.  
  3501. /****************************************************************************
  3502. get some server info
  3503. ****************************************************************************/
  3504. static void server_info()
  3505. {
  3506.   char *rparam = NULL;
  3507.   char *rdata = NULL;
  3508.   char *p;
  3509.   int rdrcnt,rprcnt;
  3510.   pstring param;
  3511.  
  3512.   bzero(param,sizeof(param));
  3513.  
  3514.   p = param;
  3515.   SSVAL(p,0,63); /* api number */
  3516.   p += 2;
  3517.   strcpy(p,"WrLh");
  3518.   p = skip_string(p,1);
  3519.   strcpy(p,"zzzBBzz");
  3520.   p = skip_string(p,1);
  3521.   SSVAL(p,0,10); /* level 10 */
  3522.   SSVAL(p,2,1000);
  3523.   p += 6;
  3524.  
  3525.   if (call_api(PTR_DIFF(p,param),0,
  3526.            6,1000,
  3527.            &rprcnt,&rdrcnt,
  3528.            param,NULL,
  3529.            &rparam,&rdata))
  3530.     {
  3531.       int res = SVAL(rparam,0);
  3532.       int converter=SVAL(rparam,2);
  3533.  
  3534.       if (res == 0)
  3535.     {
  3536.       p = rdata;
  3537.  
  3538.       printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n",
  3539.          rdata+SVAL(p,0)-converter,
  3540.          rdata+SVAL(p,4)-converter,
  3541.          rdata+SVAL(p,8)-converter,
  3542.          rdata+SVAL(p,14)-converter);
  3543.     }
  3544.     }
  3545.  
  3546.   if (rparam) free(rparam);
  3547.   if (rdata) free(rdata);
  3548.  
  3549.   return;
  3550. }
  3551.  
  3552.  
  3553. /****************************************************************************
  3554. try and browse available connections on a host
  3555. ****************************************************************************/
  3556. static BOOL list_servers()
  3557. {
  3558.   char *rparam = NULL;
  3559.   char *rdata = NULL;
  3560.   int rdrcnt,rprcnt;
  3561.   char *p;
  3562.   pstring param;
  3563.   int uLevel = 1;
  3564.   int count = 0;
  3565.  
  3566.   int servertype = SV_TYPE_ALL; 
  3567.  
  3568.   /* now send a SMBtrans command with api ServerEnum? */
  3569.   p = param;
  3570.   SSVAL(p,0,0x68); /* api number */
  3571.   p += 2;
  3572.   strcpy(p,"WrLehDO");
  3573.   p = skip_string(p,1);
  3574.  
  3575.   strcpy(p,"B16BBDz");
  3576. #if 0
  3577.   strcpy(p,getenv("XX_STR2"));
  3578. #endif
  3579.  
  3580.   p = skip_string(p,1);
  3581.   SSVAL(p,0,uLevel);
  3582.   SSVAL(p,2,0x2000); /* buf length */
  3583.   p += 4;
  3584.   SIVAL(p,0,servertype);
  3585.   p += 4;
  3586.  
  3587.   if (call_api(PTR_DIFF(p,param),0,
  3588.            8,10000,
  3589.            &rprcnt,&rdrcnt,
  3590.            param,NULL,
  3591.            &rparam,&rdata))
  3592.     {
  3593.       int res = SVAL(rparam,0);
  3594.       int converter=SVAL(rparam,2);
  3595.       int i;
  3596.  
  3597.       if (res == 0)
  3598.     {
  3599.       count=SVAL(rparam,4);
  3600.       p = rdata;
  3601.  
  3602.       if (count > 0)
  3603.     {
  3604.       printf("\n\nThis machine has a browse list:\n");
  3605.       printf("\n\tServer               Comment\n");
  3606.       printf("\t---------            -------\n");
  3607.     }
  3608.  
  3609.       for (i=0;i<count;i++)
  3610.     {
  3611.       char *sname = p;
  3612.       int comment_offset = IVAL(p,22) & 0xFFFF;
  3613.       printf("\t%-16.16s     %s\n",
  3614.          sname,
  3615.          comment_offset?rdata+comment_offset-converter:"");
  3616.       
  3617.       p += 26;
  3618.     }
  3619.     }
  3620.     }
  3621.  
  3622.   if (rparam) free(rparam);
  3623.   if (rdata) free(rdata);
  3624.  
  3625.   return(count>0);
  3626. }
  3627.  
  3628.  
  3629.  
  3630.  
  3631. void cmd_help();
  3632.  
  3633. /* This defines the commands supported by this client */
  3634. struct
  3635. {
  3636.   char *name;
  3637.   void (*fn)();
  3638.   char *description;
  3639. } commands[] = 
  3640. {
  3641.   {"ls",cmd_dir,"<mask> list the contents of the current directory"},
  3642.   {"dir",cmd_dir,"<mask> list the contents of the current directory"},
  3643.   {"lcd",cmd_lcd,"[directory] change/report the local current working directory"},
  3644.   {"cd",cmd_cd,"[directory] change/report the remote directory"},
  3645.   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"},
  3646.   {"get",cmd_get,"<remote name> [local name] get a file"},
  3647.   {"mget",cmd_mget,"<mask> get all the matching files"},
  3648.   {"put",cmd_put,"<local name> [remote name] put a file"},
  3649.   {"mput",cmd_mput,"<mask> put all matching files"},
  3650.   {"rename",cmd_rename,"<src> <dest> rename some files"},
  3651.   {"more",cmd_more,"<remote name> view a remote file with your pager"},  
  3652.   {"mask",cmd_select,"<mask> mask all filenames against this"},
  3653.   {"del",cmd_del,"<mask> delete all matching files"},
  3654.   {"rm",cmd_del,"<mask> delete all matching files"},
  3655.   {"mkdir",cmd_mkdir,"<directory> make a directory"},
  3656.   {"md",cmd_mkdir,"<directory> make a directory"},
  3657.   {"rmdir",cmd_rmdir,"<directory> remove a directory"},
  3658.   {"rd",cmd_rmdir,"<directory> remove a directory"},
  3659.   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},  
  3660.   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},  
  3661.   {"translate",cmd_translate,"toggle text translation for printing"},  
  3662.   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"},  
  3663.   {"print",cmd_print,"<file name> print a file"},
  3664.   {"printmode",cmd_printmode,"<graphics or text> set the print mode"},
  3665.   {"queue",cmd_queue,"show the print queue"},
  3666.   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
  3667.   {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
  3668.   {"quit",send_logout,"logoff the server"},
  3669.   {"q",send_logout,"logoff the server"},
  3670.   {"exit",send_logout,"logoff the server"},
  3671.   {"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
  3672.   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"},
  3673.   {"tar",cmd_tar,"tar current directory to <file name>" },
  3674.   {"blocksize",cmd_block,"blocksize <number> (default 20)" },
  3675.   {"tarmode",cmd_tarmode,
  3676.      "<mode=full|inc|reset|noreset> tar's behaviour towards archive bits" },
  3677.   {"setmode",cmd_setmode,"filename <setmode string> change modes of file"},
  3678.   {"help",cmd_help,"[command] give help on a command"},
  3679.   {"?",cmd_help,"[command] give help on a command"},
  3680.   {"!",NULL,"run a shell command on the local system"},
  3681.   {"",NULL,NULL}
  3682. };
  3683.  
  3684.  
  3685. /*******************************************************************
  3686.   lookup a command string in the list of commands, including 
  3687.   abbreviations
  3688.   ******************************************************************/
  3689. static int process_tok(fstring tok)
  3690. {
  3691.   int i = 0, matches = 0;
  3692.   int cmd;
  3693.   int tok_len = strlen(tok);
  3694.   
  3695.   while (commands[i].fn != NULL)
  3696.     {
  3697.       if (strequal(commands[i].name,tok))
  3698.     {
  3699.       matches = 1;
  3700.       cmd = i;
  3701.       break;
  3702.     }
  3703.       else if (strnequal(commands[i].name, tok, tok_len+1))
  3704.     {
  3705.       matches++;
  3706.       cmd = i;
  3707.     }
  3708.       i++;
  3709.     }
  3710.   
  3711.   if (matches == 0)
  3712.     return(-1);
  3713.   else if (matches == 1)
  3714.     return(cmd);
  3715.   else
  3716.     return(-2);
  3717. }
  3718.  
  3719. /****************************************************************************
  3720. help
  3721. ****************************************************************************/
  3722. void cmd_help(void)
  3723. {
  3724.   int i=0,j;
  3725.   fstring buf;
  3726.  
  3727.   if (next_token(NULL,buf,NULL))
  3728.     {
  3729.       if ((i = process_tok(buf)) >= 0)
  3730.     DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description));            
  3731.     }
  3732.   else
  3733.     while (commands[i].description)
  3734.       {
  3735.     for (j=0; commands[i].description && (j<5); j++) {
  3736.       DEBUG(0,("%-15s",commands[i].name));
  3737.       i++;
  3738.     }
  3739.     DEBUG(0,("\n"));
  3740.       }
  3741. }
  3742.  
  3743. /****************************************************************************
  3744. open the client sockets
  3745. ****************************************************************************/
  3746. static BOOL open_sockets(int port )
  3747. {
  3748.   static int last_port;
  3749.   char *host;
  3750.   pstring service2;
  3751.   extern int Client;
  3752.  
  3753.   if (port == 0) port=last_port;
  3754.   last_port=port;
  3755.  
  3756.   strupper(service);
  3757.  
  3758.   if (*desthost)
  3759.     {
  3760.       host = desthost;
  3761.     }
  3762.   else
  3763.     {
  3764.       strcpy(service2,service);
  3765.       host = strtok(service2,"\\/");
  3766.       strcpy(desthost,host);
  3767.     }
  3768.  
  3769.   DEBUG(3,("Opening sockets\n"));
  3770.  
  3771.   if (*myname == 0)
  3772.     {
  3773.       get_myname(myname,NULL);
  3774.       strupper(myname);
  3775.     }
  3776.  
  3777.   if (!have_ip)
  3778.     {
  3779.       struct hostent *hp;
  3780.  
  3781.       if ((hp = Get_Hostbyname(host)) == 0) 
  3782.     {
  3783.       DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
  3784.       return False;
  3785.     }
  3786.  
  3787.       putip((char *)&dest_ip,(char *)hp->h_addr);
  3788.     }
  3789.  
  3790.   Client = open_socket_out(SOCK_STREAM, &dest_ip, port);
  3791.   if (Client == -1)
  3792.     return False;
  3793.  
  3794.   DEBUG(3,("Connected\n"));
  3795.  
  3796.   set_socket_options(Client,user_socket_options);  
  3797.  
  3798.   return True;
  3799. }
  3800.  
  3801. /****************************************************************************
  3802. wait for keyboard activity, swallowing network packets
  3803. ****************************************************************************/
  3804. #ifdef CLIX
  3805. static char wait_keyboard(char *buffer)
  3806. #else
  3807. static void wait_keyboard(char *buffer)
  3808. #endif
  3809. {
  3810.   fd_set fds;
  3811.   int selrtn;
  3812.   struct timeval timeout;
  3813.   
  3814. #ifdef CLIX
  3815.   int delay = 0;
  3816. #endif
  3817.   
  3818.   while (1) 
  3819.     {
  3820.       extern int Client;
  3821.       FD_ZERO(&fds);
  3822.       FD_SET(Client,&fds);
  3823. #ifndef CLIX
  3824.       FD_SET(fileno(stdin),&fds);
  3825. #endif
  3826.  
  3827.       timeout.tv_sec = 20;
  3828.       timeout.tv_usec = 0;
  3829. #ifdef CLIX
  3830.       timeout.tv_sec = 0;
  3831. #endif
  3832.       selrtn = sys_select(&fds,&timeout);
  3833.       
  3834. #ifndef CLIX
  3835.       if (FD_ISSET(fileno(stdin),&fds))
  3836.       return;
  3837. #else
  3838.       {
  3839.     char ch;
  3840.     int f_flags;
  3841.     int readret;
  3842.     
  3843.     f_flags = fcntl(fileno(stdin), F_GETFL, 0);
  3844.     fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK);
  3845.     readret = read_data( fileno(stdin), &ch, 1);
  3846.     fcntl(fileno(stdin), F_SETFL, f_flags);
  3847.     if (readret == -1)
  3848.       {
  3849.         if (errno != EAGAIN)
  3850.           {
  3851.         /* should crash here */
  3852.         DEBUG(1,("readchar stdin failed\n"));
  3853.           }
  3854.       }
  3855.     else if (readret != 0)
  3856.       {
  3857.         return ch;
  3858.       }
  3859.       }
  3860. #endif
  3861.       if (FD_ISSET(Client,&fds))
  3862.       receive_smb(Client,buffer,0);
  3863.       
  3864. #ifdef CLIX
  3865.       delay++;
  3866.       if (delay > 100000)
  3867.     {
  3868.       delay = 0;
  3869.       chkpath("\\",False);
  3870.     }
  3871. #else
  3872.       chkpath("\\",False);
  3873. #endif
  3874.     }  
  3875. }
  3876.  
  3877.  
  3878. /****************************************************************************
  3879. close and open the connection again
  3880. ****************************************************************************/
  3881. BOOL reopen_connection(char *inbuf,char *outbuf)
  3882. {
  3883.   static int open_count=0;
  3884.  
  3885.   open_count++;
  3886.  
  3887.   if (open_count>5) return(False);
  3888.  
  3889.   DEBUG(1,("Trying to re-open connection\n"));
  3890.  
  3891.   set_message(outbuf,0,0,True);
  3892.   SCVAL(outbuf,smb_com,SMBtdis);
  3893.   SSVAL(outbuf,smb_tid,cnum);
  3894.   setup_pkt(outbuf);
  3895.  
  3896.   send_smb(Client,outbuf);
  3897.   receive_smb(Client,inbuf,SHORT_TIMEOUT);
  3898.  
  3899.   close_sockets();
  3900.   if (!open_sockets(0)) return(False);
  3901.  
  3902.   return(send_login(inbuf,outbuf,True,True));
  3903. }
  3904.  
  3905. /****************************************************************************
  3906.   process commands from the client
  3907. ****************************************************************************/
  3908. BOOL process(void )
  3909. {
  3910.   extern FILE *dbf;
  3911.   pstring line;
  3912.  
  3913.   char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3914.   char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3915.  
  3916.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3917.     return(False);
  3918.   
  3919.   bzero(OutBuffer,smb_size);
  3920.  
  3921.   if (!send_login(InBuffer,OutBuffer,True,True))
  3922.     return(False);
  3923.  
  3924.   while (!feof(stdin))
  3925.     {
  3926.       fstring tok;
  3927.       int i;
  3928.  
  3929.       bzero(OutBuffer,smb_size);
  3930.  
  3931.       /* display a prompt */
  3932.       DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir)));
  3933.       fflush(dbf);
  3934.  
  3935. #ifdef CLIX
  3936.       line[0] = wait_keyboard(InBuffer);
  3937.       /* this might not be such a good idea... */
  3938.       if ( line[0] == EOF)
  3939.     break;
  3940. #else
  3941.       wait_keyboard(InBuffer);
  3942. #endif
  3943.   
  3944.       /* and get a response */
  3945. #ifdef CLIX
  3946.       fgets( &line[1],999, stdin);
  3947. #else
  3948.       if (!fgets(line,1000,stdin))
  3949.     break;
  3950. #endif
  3951.  
  3952.       /* input language code to internal one */
  3953.       CNV_INPUT (line);
  3954.  
  3955.       /* special case - first char is ! */
  3956.       if (*line == '!')
  3957.     {
  3958.       system(line + 1);
  3959.       continue;
  3960.     }
  3961.       
  3962.       /* and get the first part of the command */
  3963.       {
  3964.     char *ptr = line;
  3965.     if (!next_token(&ptr,tok,NULL)) continue;
  3966.       }
  3967.  
  3968.       if ((i = process_tok(tok)) >= 0)
  3969.     commands[i].fn(InBuffer,OutBuffer);
  3970.       else if (i == -2)
  3971.     DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok)));
  3972.       else
  3973.     DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
  3974.     }
  3975.   
  3976.   send_logout();
  3977.   return(True);
  3978. }
  3979.  
  3980.  
  3981. /****************************************************************************
  3982. usage on the program
  3983. ****************************************************************************/
  3984. void usage(char *pname)
  3985. {
  3986.   DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
  3987.        pname));
  3988.  
  3989. #ifdef KANJI
  3990.   DEBUG(0,("[-t termcode] "));
  3991. #endif /* KANJI */
  3992.  
  3993.   DEBUG(0,("\nVersion %s\n",VERSION));
  3994.   DEBUG(0,("\t-p port               listen on the specified port\n"));
  3995.   DEBUG(0,("\t-d debuglevel         set the debuglevel\n"));
  3996.   DEBUG(0,("\t-l log basename.      Basename for log/debug files\n"));
  3997.   DEBUG(0,("\t-n netbios name.      Use this name as my netbios name\n"));
  3998.   DEBUG(0,("\t-N                    don't ask for a password\n"));
  3999.   DEBUG(0,("\t-P                    connect to service as a printer\n"));
  4000.   DEBUG(0,("\t-M host               send a winpopup message to the host\n"));
  4001.   DEBUG(0,("\t-m max protocol       set the max protocol level\n"));
  4002.   DEBUG(0,("\t-L host               get a list of shares available on a host\n"));
  4003.   DEBUG(0,("\t-I dest IP            use this IP to connect to\n"));
  4004.   DEBUG(0,("\t-E                    write messages to stderr instead of stdout\n"));
  4005.   DEBUG(0,("\t-U username           set the network username\n"));
  4006.   DEBUG(0,("\t-W workgroup          set the workgroup name\n"));
  4007. #ifdef KANJI
  4008.   DEBUG(0,("\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
  4009. #endif /* KANJI */
  4010.   DEBUG(0,("\n"));
  4011. }
  4012.  
  4013.  
  4014.  
  4015. /****************************************************************************
  4016.   main program
  4017. ****************************************************************************/
  4018. int main(int argc,char *argv[])
  4019. {
  4020.   char *pname = argv[0];
  4021.   int port = 139;
  4022.   int opt;
  4023.   extern FILE *dbf;
  4024.   extern char *optarg;
  4025.   pstring query_host;
  4026.   BOOL message = False;
  4027.  
  4028.   *query_host = 0;
  4029.  
  4030.   DEBUGLEVEL = 2;
  4031.  
  4032.   setup_logging(pname,True);
  4033.  
  4034.   TimeInit();
  4035.   charset_initialise();
  4036.  
  4037.   pid = getpid();
  4038.   uid = getuid();
  4039.   gid = getgid();
  4040.   mid = pid + 100;
  4041.   myumask = umask(0);
  4042.   umask(myumask);
  4043.  
  4044.   if (getenv("USER"))
  4045.     {
  4046.       strcpy(username,getenv("USER"));
  4047.       strupper(username);
  4048.     }
  4049.  
  4050.   if (*username == 0 && getenv("LOGNAME"))
  4051.     {
  4052.       strcpy(username,getenv("LOGNAME"));
  4053.       strupper(username);
  4054.     }
  4055.  
  4056.   if (argc < 2)
  4057.     {
  4058.       usage(pname);
  4059.       exit(1);
  4060.     }
  4061.   
  4062.   if (*argv[1] != '-')
  4063.     {
  4064.  
  4065.       strcpy(service,argv[1]);  
  4066.       argc--;
  4067.       argv++;
  4068.  
  4069.       if (count_chars(service,'\\') < 3)
  4070.     {
  4071.       usage(pname);
  4072.       printf("\n%s: Not enough '\\' characters in service\n",service);
  4073.       exit(1);
  4074.     }
  4075.  
  4076. /*
  4077.       if (count_chars(service,'\\') > 3)
  4078.     {
  4079.       usage(pname);
  4080.       printf("\n%s: Too many '\\' characters in service\n",service);
  4081.       exit(1);
  4082.     }
  4083.     */
  4084.  
  4085.       if (argc > 1 && (*argv[1] != '-'))
  4086.     {
  4087.       got_pass = True;
  4088.       strcpy(password,argv[1]);  
  4089.       memset(argv[1],'X',strlen(argv[1]));
  4090.       argc--;
  4091.       argv++;
  4092.     }
  4093.     }
  4094.  
  4095. #ifdef KANJI
  4096.   setup_term_code (KANJI);
  4097.   while ((opt = getopt (argc, argv, "O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:")) != EOF)
  4098. #else
  4099.   while ((opt = getopt (argc, argv, "O:M:i:Nn:d:Pp:l:hI:EB:U:L:m:W:")) != EOF)
  4100. #endif /* KANJI */
  4101.     switch (opt)
  4102.       {
  4103.       case 'm':
  4104.     max_protocol = interpret_protocol(optarg,max_protocol);
  4105.     break;
  4106.       case 'O':
  4107.     strcpy(user_socket_options,optarg);
  4108.     break;    
  4109.       case 'M':
  4110.     name_type = 3;
  4111.     strcpy(desthost,optarg);
  4112.     strupper(desthost);
  4113.     message = True;
  4114.     break;
  4115.       case 'i':
  4116.     strcpy(scope,optarg);
  4117.     break;
  4118.       case 'L':
  4119.     got_pass = True;
  4120.     strcpy(query_host,optarg);
  4121.     break;
  4122.       case 'U':
  4123.     {
  4124.       char *p;
  4125.     strcpy(username,optarg);
  4126.     if ((p=strchr(username,'%')))
  4127.       {
  4128.         *p = 0;
  4129.         strcpy(password,p+1);
  4130.         got_pass = True;
  4131.         memset(strchr(optarg,'%')+1,'X',strlen(password));
  4132.       }
  4133.     }
  4134.         
  4135.     break;
  4136.       case 'W':
  4137.     strcpy(workgroup,optarg);
  4138.     break;
  4139.       case 'E':
  4140.     dbf = stderr;
  4141.     break;
  4142.       case 'I':
  4143.     {
  4144.       dest_ip = *interpret_addr2(optarg);
  4145.       if (zero_ip(dest_ip)) exit(1);
  4146.       have_ip = True;
  4147.     }
  4148.     break;
  4149.       case 'n':
  4150.     strcpy(myname,optarg);
  4151.     break;
  4152.       case 'N':
  4153.     got_pass = True;
  4154.     break;
  4155.       case 'P':
  4156.     connect_as_printer = True;
  4157.     break;
  4158.       case 'd':
  4159.     if (*optarg == 'A')
  4160.       DEBUGLEVEL = 10000;
  4161.     else
  4162.       DEBUGLEVEL = atoi(optarg);
  4163.     break;
  4164.       case 'l':
  4165.     sprintf(debugf,"%s.client",optarg);
  4166.     break;
  4167.       case 'p':
  4168.     port = atoi(optarg);
  4169.     break;
  4170.       case 'h':
  4171.     usage(pname);
  4172.     exit(0);
  4173.     break;
  4174. #ifdef KANJI
  4175.       case 't':
  4176.     if (!setup_term_code (optarg)) {
  4177.         DEBUG(0, ("%s: unknown terminal code name\n", optarg));
  4178.         usage (pname);
  4179.         exit (1);
  4180.     }
  4181.     break;
  4182. #endif /* KANJI */
  4183.       default:
  4184.     usage(pname);
  4185.     exit(1);
  4186.       }
  4187.  
  4188.   if (!*query_host && !*service && !message)
  4189.     {
  4190.       usage(pname);
  4191.       exit(1);
  4192.     }
  4193.  
  4194.  
  4195.   DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
  4196.  
  4197.   get_myname(*myname?NULL:myname,&myip);  
  4198.   strupper(myname);
  4199.   
  4200.   if (*query_host)
  4201.     {
  4202.       int ret = 0;
  4203.       sprintf(service,"\\\\%s\\IPC$",query_host);
  4204.       strupper(service);
  4205.       connect_as_ipc = True;
  4206.       if (open_sockets(port))
  4207.     {
  4208. #if 0
  4209.       *username = 0;
  4210. #endif
  4211.       if (!send_login(NULL,NULL,True,True))
  4212.         return(1);
  4213.  
  4214.       server_info();
  4215.       if (!browse_host(True)) {
  4216.         sleep(1);
  4217.         browse_host(True);
  4218.       }
  4219.       if (!list_servers()) {
  4220.         sleep(1);
  4221.         list_servers();
  4222.       }
  4223.  
  4224.       send_logout();
  4225.       close_sockets();
  4226.     }
  4227.  
  4228.       return(ret);
  4229.     }
  4230.  
  4231.   if (message)
  4232.     {
  4233.       int ret = 0;
  4234.       if (open_sockets(port))
  4235.     {
  4236.       pstring inbuf,outbuf;
  4237.       bzero(outbuf,smb_size);
  4238.       if (!send_session_request(inbuf,outbuf))
  4239.         return(1);
  4240.  
  4241.       send_message(inbuf,outbuf);
  4242.  
  4243.       close_sockets();
  4244.     }
  4245.  
  4246.       return(ret);
  4247.     }
  4248.  
  4249.   if (open_sockets(port))
  4250.     {
  4251.       if (!process())
  4252.     {
  4253.       close_sockets();
  4254.       return(1);
  4255.     }
  4256.       close_sockets();
  4257.     }
  4258.   else
  4259.     return(1);
  4260.  
  4261.   return(0);
  4262. }
  4263.  
  4264.  
  4265. /* error code stuff - put together by Merik Karman
  4266.    merik@blackadder.dsh.oz.au */
  4267.  
  4268. typedef struct
  4269. {
  4270.   char *name;
  4271.   int code;
  4272.   char *message;
  4273. } err_code_struct;
  4274.  
  4275. /* Dos Error Messages */
  4276. err_code_struct dos_msgs[] = {
  4277.   {"ERRbadfunc",1,"Invalid function."},
  4278.   {"ERRbadfile",2,"File not found."},
  4279.   {"ERRbadpath",3,"Directory invalid."},
  4280.   {"ERRnofids",4,"No file descriptors available"},
  4281.   {"ERRnoaccess",5,"Access denied."},
  4282.   {"ERRbadfid",6,"Invalid file handle."},
  4283.   {"ERRbadmcb",7,"Memory control blocks destroyed."},
  4284.   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
  4285.   {"ERRbadmem",9,"Invalid memory block address."},
  4286.   {"ERRbadenv",10,"Invalid environment."},
  4287.   {"ERRbadformat",11,"Invalid format."},
  4288.   {"ERRbadaccess",12,"Invalid open mode."},
  4289.   {"ERRbaddata",13,"Invalid data."},
  4290.   {"ERR",14,"reserved."},
  4291.   {"ERRbaddrive",15,"Invalid drive specified."},
  4292.   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
  4293.   {"ERRdiffdevice",17,"Not same device."},
  4294.   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
  4295.   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
  4296.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."},
  4297.   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
  4298.   {"ERRbadpipe",230,"Pipe invalid."},
  4299.   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
  4300.   {"ERRpipeclosing",232,"Pipe close in progress."},
  4301.   {"ERRnotconnected",233,"No process on other end of pipe."},
  4302.   {"ERRmoredata",234,"There is more data to be returned."},
  4303.   {NULL,-1,NULL}};
  4304.  
  4305. /* Server Error Messages */
  4306. err_code_struct server_msgs[] = {
  4307.   {"ERRerror",1,"Non-specific error code."},
  4308.   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
  4309.   {"ERRbadtype",3,"reserved."},
  4310.   {"ERRaccess",4,"The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."},
  4311.   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
  4312.   {"ERRinvnetname",6,"Invalid network name in tree connect."},
  4313.   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
  4314.   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
  4315.   {"ERRqtoobig",50,"Print queue full -- no space."},
  4316.   {"ERRqeof",51,"EOF on print queue dump."},
  4317.   {"ERRinvpfid",52,"Invalid print file FID."},
  4318.   {"ERRsmbcmd",64,"The server did not recognize the command received."},
  4319.   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
  4320.   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
  4321.   {"ERRreserved",68,"reserved."},
  4322.   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
  4323.   {"ERRreserved",70,"reserved."},
  4324.   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
  4325.   {"ERRpaused",81,"Server is paused."},
  4326.   {"ERRmsgoff",82,"Not receiving messages."},
  4327.   {"ERRnoroom",83,"No room to buffer message."},
  4328.   {"ERRrmuns",87,"Too many remote user names."},
  4329.   {"ERRtimeout",88,"Operation timed out."},
  4330.   {"ERRnoresource",89,"No resources currently available for request."},
  4331.   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
  4332.   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
  4333.   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
  4334.   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
  4335.   {"ERRcontmpx",252,"Continue in MPX mode."},
  4336.   {"ERRreserved",253,"reserved."},
  4337.   {"ERRreserved",254,"reserved."},
  4338.   {"ERRnosupport",0xFFFF,"Function not supported."},
  4339.   {NULL,-1,NULL}};
  4340.  
  4341. /* Hard Error Messages */
  4342. err_code_struct hard_msgs[] = {
  4343.   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
  4344.   {"ERRbadunit",20,"Unknown unit."},
  4345.   {"ERRnotready",21,"Drive not ready."},
  4346.   {"ERRbadcmd",22,"Unknown command."},
  4347.   {"ERRdata",23,"Data error (CRC)."},
  4348.   {"ERRbadreq",24,"Bad request structure length."},
  4349.   {"ERRseek",25 ,"Seek error."},
  4350.   {"ERRbadmedia",26,"Unknown media type."},
  4351.   {"ERRbadsector",27,"Sector not found."},
  4352.   {"ERRnopaper",28,"Printer out of paper."},
  4353.   {"ERRwrite",29,"Write fault."},
  4354.   {"ERRread",30,"Read fault."},
  4355.   {"ERRgeneral",31,"General failure."},
  4356.   {"ERRbadshare",32,"A open conflicts with an existing open."},
  4357.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
  4358.   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
  4359.   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
  4360.   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
  4361.   {NULL,-1,NULL}};
  4362.  
  4363.  
  4364. struct
  4365. {
  4366.   int code;
  4367.   char *class;
  4368.   err_code_struct *err_msgs;
  4369. } err_classes[] = { 
  4370.   {0,"SUCCESS",NULL},
  4371.   {0x01,"ERRDOS",dos_msgs},
  4372.   {0x02,"ERRSRV",server_msgs},
  4373.   {0x03,"ERRHRD",hard_msgs},
  4374.   {0x04,"ERRXOS",NULL},
  4375.   {0xE1,"ERRRMX1",NULL},
  4376.   {0xE2,"ERRRMX2",NULL},
  4377.   {0xE3,"ERRRMX3",NULL},
  4378.   {0xFF,"ERRCMD",NULL},
  4379.   {-1,NULL,NULL}};
  4380.  
  4381.  
  4382. /****************************************************************************
  4383. return a SMB error string from a SMB buffer
  4384. ****************************************************************************/
  4385. char *smb_errstr(char *inbuf)
  4386. {
  4387.   static pstring ret;
  4388.   int class = CVAL(inbuf,smb_rcls);
  4389.   int num = SVAL(inbuf,smb_err);
  4390.   int i,j;
  4391.  
  4392.   for (i=0;err_classes[i].class;i++)
  4393.     if (err_classes[i].code == class)
  4394.       {
  4395.     if (err_classes[i].err_msgs)
  4396.       {
  4397.         err_code_struct *err = err_classes[i].err_msgs;
  4398.         for (j=0;err[j].name;j++)
  4399.           if (num == err[j].code)
  4400.         {
  4401.           if (DEBUGLEVEL > 0)
  4402.             sprintf(ret,"%s - %s (%s)",err_classes[i].class,
  4403.                 err[j].name,err[j].message);
  4404.           else
  4405.             sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
  4406.           return ret;
  4407.         }
  4408.       }
  4409.  
  4410.     sprintf(ret,"%s - %d",err_classes[i].class,num);
  4411.     return ret;
  4412.       }
  4413.   
  4414.   sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
  4415.   return(ret);
  4416. }
  4417.